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

查看:19
本文介绍了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(呃哦……)并用它来注解每个 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?

Is it possible to destroy aCDI 范围? 我会看一下,但需要一些关于范围界定是否是正当理由的备份.

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天全站免登陆