Pregunta

Estoy tratando de crear instancias de frijoles administrados por CDI usando el beanManager en lugar de instancia .select (). Get ().

Esto se sugirió como una solución para un problema que he estado teniendo con las aplicaciones recolectadas de frijoles y basura de sus dependientes, ver ¿La aplicación CDI y los ámbitos dependientes pueden conspirar para impactar la recolección de basura? para antecedentes y esta solución sugerida.

Si usa el método de búsqueda programática de instancia en un bean de aplicaciones, el objeto de instancia y cualquier granos que obtenga de él, en última instancia, dependen de las aplicaciones y, por lo tanto, comparta su ciclo de vida. Sin embargo, si crea frijoles con el beanmanager, tiene un mango en la instancia de Bean en sí, y aparentemente puede destruirlo explícitamente, lo que entiendo significa que será Ged.

Mi enfoque actual es crear el bean dentro de una clase de beangerutil y devolver un objeto compuesto de bean, instancia y creaciónContext:

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);
    }
}

De esto, en el código de llamadas, puedo obtener la instancia real, ponerla en un mapa para una recuperación posterior y usarlo como normal:

private Map<Worker, DestructibleBeanInstance<Worker>> beansByTheirWorkers =
    new HashMap<Worker, DestructibleBeanInstance<Worker>>();
...
DestructibleBeanInstance<Worker> destructible =
        beanUtils.getDestructibleBeanInstance(Worker.class, workerBindingQualifier);
Worker worker = destructible.getInstance();
...

Cuando termine con él, puedo buscar el envoltorio destructible y llamar a destruir (), y el frijol y sus dependientes deben limpiarse:

DestructibleBeanInstance<JamWorker> workerBean =
        beansByTheirWorkers.remove(worker);
workerBean.destroy();
worker = null;

Sin embargo, después de ejecutar varios trabajadores y dejar mi JBoss (7.1.0.alpha1-snapshot) durante aproximadamente 20 minutos más o menos, puedo ver que GC está ocurriendo

2011.002: [GC
Desired survivor size 15794176 bytes, new threshold 1 (max 15)
1884205K->1568621K(3128704K), 0.0091281 secs]

Sin embargo, un histograma de JMAP todavía muestra a los viejos trabajadores y sus instancias dependientes dando vueltas. ¿Qué me estoy perdiendo?

A través de la depuración, puedo ver que el campo de contexto del bean creado tiene el contextual del tipo de trabajador correcto, sin estancias incompletas y no se dependientes de la matriz. Tiene una serie de servicios dependientes, que son los esperados de los campos del trabajador.

Uno de estos campos en el trabajador es en realidad una instancia, y cuando comparo este campo con el de un trabajador recuperado a través de la búsqueda programática de instancias, tienen un maquillaje creationalcontext ligeramente diferente. El campo de la instancia en el trabajador levantó la vista a través de la instancia tiene al trabajador en sí mismo en incompletinstance, mientras que el campo de instancia en el trabajador recuperado del beanmanager no lo hace. Ambos tienen dependencias parentales y dependientes idénticas.

Esto me sugiere que no he reflejado correctamente la recuperación de la instancia. ¿Podría esto estar contribuyendo a la falta de destrucción?

Finalmente, al depurar, puedo ver que Bean.destroy () se llame en mi destructible BeanInstance.destroy (), y esto se dedica a ManagedBean.DestrOY, y puedo ver que los objetos dependientes se destruyen como parte de .release (). ¡Sin embargo, todavía no se recolectan basura!

¡Cualquier ayuda en esto sería muy apreciada! Gracias.

No hay solución correcta

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top