Ben*_*rby 7 java garbage-collection cdi managed-bean jboss-weld
我正在尝试使用BeanManager而不是Instance .select().get()创建CDI托管bean的实例.
这被建议作为我已经使用ApplicationScoped bean和他们的家属的垃圾收集的问题的解决方法 - 请参阅CDI应用程序和依赖范围可以合谋影响垃圾收集?对于背景和建议的解决方法.
如果在ApplicationScoped bean上使用Instance编程查找方法,Instance对象和从中获取的任何bean最终都依赖于ApplicationScoped bean,因此共享它的生命周期.但是,如果使用BeanManager创建bean,则会在Bean实例本身上设置句柄,并且显然可以明确地销毁它,我理解这意味着它将被GCed.
我目前的方法是在BeanManagerUtil类中创建bean,并返回Bean,实例和CreationalContext的复合对象:
public class BeanManagerUtil {
@Inject private BeanManager beanManager;
@SuppressWarnings("unchecked")
public <T> DestructibleBeanInstance<T> getDestructibleBeanInstance(final Class<T> type,
final Annotation... qualifiers) {
DestructibleBeanInstance<T> result = null;
Bean<T> bean = (Bean<T>) beanManager.resolve(beanManager.getBeans(type, qualifiers));
if (bean != null) {
CreationalContext<T> creationalContext = beanManager.createCreationalContext(bean);
if (creationalContext != null) {
T instance = bean.create(creationalContext);
result = new DestructibleBeanInstance<T>(instance, bean, creationalContext);
}
}
return result;
}
}
public class DestructibleBeanInstance<T> {
private T instance;
private Bean<T> bean;
private CreationalContext<T> context;
public DestructibleBeanInstance(T instance, Bean<T> bean, CreationalContext<T> context) {
this.instance = instance;
this.bean = bean;
this.context = context;
}
public T getInstance() {
return instance;
}
public void destroy() {
bean.destroy(instance, context);
}
}
Run Code Online (Sandbox Code Playgroud)
从这里,在调用代码中,我可以获得实际的实例,将其放在地图中供以后检索,并正常使用:
private Map<Worker, DestructibleBeanInstance<Worker>> beansByTheirWorkers =
new HashMap<Worker, DestructibleBeanInstance<Worker>>();
...
DestructibleBeanInstance<Worker> destructible =
beanUtils.getDestructibleBeanInstance(Worker.class, workerBindingQualifier);
Worker worker = destructible.getInstance();
...
Run Code Online (Sandbox Code Playgroud)
当我完成它时,我可以查找可破坏的包装器并在其上调用destroy(),并且应该清理bean及其依赖项:
DestructibleBeanInstance<JamWorker> workerBean =
beansByTheirWorkers.remove(worker);
workerBean.destroy();
worker = null;
Run Code Online (Sandbox Code Playgroud)
然而,在运行几个工作人员并离开我的JBoss(7.1.0.Alpha1-SNAPSHOT)20分钟左右后,我可以看到GC发生
2011.002: [GC
Desired survivor size 15794176 bytes, new threshold 1 (max 15)
1884205K->1568621K(3128704K), 0.0091281 secs]
Run Code Online (Sandbox Code Playgroud)
然而,JMAP直方图仍然显示旧工人及其依赖的实例,unGCed.我错过了什么?
通过调试,我可以看到创建的bean的上下文字段具有正确的Worker类型的上下文,没有incompleteInstances,也没有parentDependentInstances.它有许多dependentInstances,它们与worker上的字段一样.
Worker上的其中一个字段实际上是一个实例,当我将此字段与通过编程实例查找检索到的Worker字段进行比较时,它们的CreationalContext组成略有不同.通过Instance查找的Worker上的Instance字段将worker本身置于incompleteInstances下,而从BeanManager中检索的Worker上的Instance字段则没有.它们都具有相同的parentDependentInstances和dependentInstances.
这告诉我,我没有正确反映实例的检索.这会导致缺乏破坏吗?
最后,在调试时,我可以看到在我的DestructibleBeanInstance.destroy()中调用了bean.destroy(),这将进入ManagedBean.destroy,我可以看到依赖对象被作为.release()的一部分被销毁.但是他们仍然没有收集垃圾!
任何有关这方面的帮助将非常感谢!谢谢.
我会更改您粘贴的代码中的一些内容。
BeanManager.createCreationContext(null)将为您提供一个依赖范围,您可以在完成调用后释放该范围CreationalContext.release()。您可以通过在 中已有的 CreationalContext 上调用 release 方法,让一切按照您想要的方式正常工作DestructibleBeanInstance,假设该 CreationalContext 中没有其他内容Beans会扰乱您的应用程序。首先尝试一下,看看它是否会把事情搞砸。
| 归档时间: |
|
| 查看次数: |
14347 次 |
| 最近记录: |