Domanda

Sto cercando di creare istanze di fagioli gestiti CDI usando il beanManager anziché istanza .Select (). Get ().

Questo è stato suggerito come soluzione alternativa per un problema che ho avuto con le applicazioni fagioli e la raccolta della spazzatura delle loro persone a carico - vedi L'applicazione CDI e gli ambiti dipendenti possono cospirare per avere un impatto sulla raccolta dei rifiuti? Per lo sfondo e questa soluzione alternativa suggerita.

Se si utilizza il metodo di ricerca programmatica di istanza su un fagiolo a applicazione, l'oggetto istanza e tutti i fagioli da cui si ottengono sono tutti in definitiva dipendenti dal fagiolo con le applicazioni e quindi condividi il suo ciclo di vita. Se crei fagioli con il beanmanager, tuttavia, hai una maniglia sull'istanza di fagioli stessa e a quanto pare puoi distruggerlo esplicitamente, che capisco significa che sarà gelso.

Il mio approccio attuale è quello di creare il fagiolo all'interno di una classe BeanManagerutil e restituire un oggetto composito di Bean, Instance e 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);
    }
}

Da questo, nel codice chiamante, posso quindi ottenere l'istanza effettiva, inserirla in una mappa per un recupero successivo e usare come normale:

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

Quando ho finito, posso cercare l'involucro distruttibile e chiamare Destroy () su di esso, e il fagiolo e le sue persone a carico dovrebbero essere ripulite:

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

Tuttavia, dopo aver gestito diversi lavoratori e aver lasciato il mio JBoss (7.1.0.Alpha1-Snapshot) per circa 20 minuti, posso vedere GC che si verifica

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

Eppure un istogramma JMAP mostra ancora i vecchi lavoratori e le loro istanze dipendenti in giro, non ingannate. Cosa mi manca?

Attraverso il debug, posso vedere che il campo di contesto del fagiolo creato ha il contesto del tipo di lavoratore corretto, nessuna instabilità incomplete e nessuna installazione dei genitori. Ha una serie di dipendenti, che sono come previsto dai campi sul lavoratore.

Uno di questi campi sul lavoratore è in realtà un'istanza e quando confronto questo campo con quello di un lavoratore recuperato tramite una ricerca programmatica, hanno un trucco di CreationalContext leggermente diverso. Il campo di istanza sul lavoratore ha cercato l'istanza ha il lavoratore stesso in istanze incomplete, mentre il campo di istanza sul lavoratore recuperato dal beanmanager no. Entrambi hanno identici dipendenti e dipendenti dipendenti da genitori.

Questo mi suggerisce che non ho rispecchiato correttamente il recupero dell'istanza. Questo potrebbe contribuire alla mancanza di distruzione?

Infine, durante il debug, posso vedere Bean.Destroy () essere chiamato nel mio DestructibleBeanstance.Destroy (), e questo passa a ResagedBean.Destroy, e posso vedere oggetti dipendenti che vengono distrutti come parte del .release (). Tuttavia non vengono ancora raccolti nella spazzatura!

Qualsiasi aiuto su questo sarebbe molto apprezzato! Grazie.

Nessuna soluzione corretta

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top