CDI 应用程序和从属作用域可以合谋影响垃圾收集吗? [英] CDI Application and Dependent scopes can conspire to impact garbage collection?

查看:15
本文介绍了CDI 应用程序和从属作用域可以合谋影响垃圾收集吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

We're starting to experiment with implementing our backend services using CDI. The scenario is this:

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

EJB with @Startup is started when EAR deployed. An ApplicationScoped bean is injected onto this:

@ApplicationScoped
public class JobPlatform {

    private PooledExecutor threadHolder;

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

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

The bean also has an Observer method, which, when an event is observed, gets a worker bean from the Instance workerSource and puts it on the threadPool, where it eventually runs to completion.

一切正常.但是……我们已经开始看到垃圾收集问题.JMAP 堆直方图显示,有许多这样的工作线程在附近闲逛,回收垃圾.

All working nicely. However... we've started to see garbage collection issues. A JMAP heap histogram shows that there are many of these workers hanging around, un-garbage collected.

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

We believe that this is down to the combination of CDI scoping. The API page for @Dependant (http://docs.jboss.org/cdi/api/1.0-SP1/javax/enterprise/context/Dependent.html) reinforces more clearly what's in the docs:

  • 注入字段、bean 构造函数或初始值设定项方法的具有作用域 @Dependent 的 bean 实例是注入它的 bean 或 Java EE 组件类实例的依赖对象.
  • 注入生产者方法的具有 @Dependent 作用域的 bean 实例是正在生产的生产者方法 bean 实例的依赖对象.
  • 通过直接调用 Instance 获得的具有 @Dependent 作用域的 bean 实例是 Instance 实例的依赖对象.

所以,按照这个:

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

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

Does anyone using CDI agree with this? Have you experienced this lack of garbage collection and, if so, can you suggest any workarounds?

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

The workers cannot be ApplicationScoped, yet the platform has to be. If we were to create a custom WorkerScope (uh ohhh...) and annotate each worker class with it, would that be sufficient to separate the dependency between worker and instance source?

是否有可能销毁一个CDI 范围?,我会看看,但想要一些关于范围界定是否是正当理由的备份.

There're also some suggestions at Is it possible to destroy a CDI scope? that I will look at, but wanted some backup on whether scoping looks like a valid reason.

希望能帮到你,谢谢.

推荐答案

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

Your understanding is correct. This was an oversight in the spec, and something that will be fixed in CDI 1.1. Instance can have a memory leak just like you've described when used in a long running scope such as SessionScoped or ApplicationScoped. What you will need to do is get a hold of the Contextual or Bean for the instance and destroy it that way.

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

For what you're doing, and to avoid the memory leak you're best off to use the BeanManager methods to create instances (that way you'll also have a handle on the Bean and can destroy it) instead of Instance.

这篇关于CDI 应用程序和从属作用域可以合谋影响垃圾收集吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆