CDI应用程序和依赖范围可能合谋影响垃圾收集?

Ben*_*rby 17 garbage-collection scope cdi jboss-weld

我们开始尝试使用CDI实现我们的后端服务.场景是这样的:

部署EAR时启动带有@Startup的EJB.将ApplicationScoped bean注入到此:

@ApplicationScoped
public class JobPlatform {

    private PooledExecutor threadHolder;

    @Inject @Any
    private Instance<Worker> workerSource;
...
Run Code Online (Sandbox Code Playgroud)

bean还有一个Observer方法,当观察到一个事件时,它从Instance workerSource获取一个工作bean并将它放在threadPool上,最终运行完成.

一切都很好.但是......我们已经开始看到垃圾收集问题了.JMAP堆直方图显示,这些工作人员中有许多人闲逛,没有收集垃圾.

我们认为这归结于CDI范围的结合.@Dependant的API页面(http://docs.jboss.org/cdi/api/1.0-SP1/javax/enterprise/context/Dependent.html)更清楚地强化了文档中的内容:

  • 将范围@Dependent注入字段,bean构造函数或初始化方法的bean的实例是注入它的bean或Java EE组件类实例的依赖对象.
  • 将@Dependent注入到producer方法中的bean的实例是正在生成的生成器方法bean实例的依赖对象.
  • 通过直接调用实例获得的具有范围@Dependent的bean实例是Instance实例的依赖对象.

所以,遵循这个:

  • workerSource bean绑定到JobPlatform,因此具有ApplicationScoped生存期
  • 使用该实例检索的任何工作bean都绑定到它,因此具有ApplicationScoped生存期
  • 因为ApplicationScoped上下文的beanstore(我的术语知识在这里有点模糊)仍然有对​​工作bean的引用,它们不会被破坏/垃圾收集

有没有人使用CDI同意这个?你是否经历过这种垃圾收集的缺乏,如果是这样,你能建议任何解决方法吗?

工作人员不能是ApplicationScoped,但平台必须是.如果我们要创建一个自定义的WorkerScope(嗯哦......)并使用它来注释每个工作类,那么这是否足以分离工作者和实例源之间的依赖关系?

还有一些建议是否有可能破坏CDI范围?我会看一下,但是想要确定范围看起来是否合理.

希望你能帮忙,谢谢.

Lig*_*ard 10

你的理解是正确的.这是规范中的疏忽,将在CDI 1.1中修复.Instance可以有内存泄漏在长时间运行的范围使用,如时就像你所描述SessionScopedApplicationScoped.您需要做的是获取ContextualBean保存实例并以此方式销毁它.

对于你正在做的事情,并且为了避免内存泄漏,你最好使用BeanManager方法来创建实例(这样你也Bean可以使用它来处理并且可以销毁它)而不是Instance.

  • @TomAnderson实例上将有一个remove或destroy方法(不记得具体名称),当你完成使用它时,它将释放创建的实例. (3认同)