【问题标题】:CDI Application and Dependent scopes can conspire to impact garbage collection?CDI 应用程序和从属范围会共同影响垃圾收集吗?
【发布时间】:2012-01-13 04:27:57
【问题描述】:

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

带有@Startup 的EJB 在EAR 部署时启动。一个 ApplicationScoped bean 被注入到这里:

@ApplicationScoped
public class JobPlatform {

    private PooledExecutor threadHolder;

    @Inject @Any
    private Instance<Worker> workerSource;
...

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

一切运行良好。然而......我们已经开始看到垃圾收集问题。 JMAP 堆直方图显示有许多这样的工人在闲逛,没有收集垃圾。

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

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

所以,接下来:

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

使用 CDI 的人是否同意这一点?您是否遇到过这种缺乏垃圾收集的情况,如果有,您能提出任何解决方法吗?

worker 不能是 ApplicationScoped,但平台必须是。如果我们要创建一个自定义的 WorkerScope(呃哦……)并用它来注解每个 worker 类,这是否足以分离 worker 和实例源之间的依赖关系?

Is it possible to destroy a CDI scope? 也有一些建议,我会看看,但希望对范围界定是否是一个正当理由提供一些支持。

希望你能帮忙,谢谢。

【问题讨论】:

    标签: garbage-collection scope cdi jboss-weld


    【解决方案1】:

    在研究实施 Jason 建议的解决方法时,我发现了一些与该问题相关的更多资源:

    问题:https://issues.jboss.org/browse/CDI-139https://issues.jboss.org/browse/WELD-920

    beanManager 操作示例: https://issues.jboss.org/browse/CDI-14?focusedCommentId=12601344&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-12601344

    org.jboss.seam.faces.util.BeanManagerUtils

    【讨论】:

      【解决方案2】:

      你的理解是正确的。这是规范中的疏忽,将在 CDI 1.1 中修复。 Instance 可能会发生内存泄漏,就像您在长时间运行的范围(如 SessionScopedApplicationScoped)中所描述的那样。您需要做的是获取实例的ContextualBean 并以这种方式销毁它。

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

      【讨论】:

      • 非常感谢您这么快回复 - 很高兴知道这是一个公认的问题。现在将尝试解决方法!干杯!
      • 对于其他阅读此处的人,请注意 Weld 1.1 实现 CDI 1.0,而不是 CDI 1.1。
      • 正确的克雷格。 Weld 2.0 实现了 CDI 1.1(是的,我知道编号很奇怪)。如果你想看看 CDI 1.1 会是什么样子,试试 Weld 2.0。我相信有 JBoss AS7 的特殊版本,其中包括 Weld 2.0。
      • 这在 CDI 1.1 中有何变化?
      • @TomAnderson Instance 上会有一个 remove 或 destroy 方法(不记得确切的名字),当你用完它时会释放创建的实例。
      猜你喜欢
      • 1970-01-01
      • 2011-10-22
      • 1970-01-01
      • 1970-01-01
      • 2019-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-22
      相关资源
      最近更新 更多