使用@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页面更清楚地说明了文档中的内容:
- An instance of a bean with scope @Dependent injected into a field,bean constructor or initializer method is a dependent object of the bean or Java EE component class instance into which it was injected.
- An instance of a bean with scope @Dependent injected into a producer method is a dependent object of the producer method bean instance that is being produced.
- An instance of a bean with scope @Dependent obtained by direct invocation of an Instance is a dependent object of the instance of Instance.
所以,遵循:
> workerSource bean绑定到JobPlatform,因此具有ApplicationScoped的生命周期
>使用该实例检索到的任何工作Bean都绑定到它,因此具有ApplicationScoped的生命周期
>因为ApplicationScoped上下文的beanstore(我对这个术语的了解在这里有点朦胧)仍然有一个对工作bean的引用,它们不被破坏/垃圾收集
有人使用CDI同意吗?您是否遇到过这样的垃圾收集缺陷,如果是,您能否提出任何解决方法?
工作人员不能被ApplicationScoped,但平台必须是.如果我们要创建一个自定义的WorkerScope(呃哦…)并用它来注释每个工作类,那么这样做足以分离worker和instance source之间的依赖关系?
还有一些建议,在Is it possible to destroy a CDI scope?我会看,但想要一些备份是否范围界定看起来像一个有效的理由.
希望你能帮忙,谢谢.
为了正在做什么,为避免内存泄漏,您最好使用BeanManager方法来创建实例(这样您也可以在Bean上具有一个句柄,并且可以销毁它)而不是Instance.