Question

J'essaie de créer des instances de haricots gérés par CDI à l'aide du BeanManager plutôt que d'instance .Select (). Get ().

Cela a été suggéré comme solution de contournement à un problème que j'ai eu avec des applications de haricots et de collecte d'ordures de leurs personnes à charge - voir L'application CDI et les lunettes dépendantes peuvent conspirer pour avoir un impact sur la collecte des ordures? pour le contexte et cela suggérait une solution de contournement.

Si vous utilisez la méthode de recherche programmatique d'instance sur un bean Coped Applications, l'objet d'instance et tous les haricots que vous en retirez dépendent finalement du bean Coped Applications, et partagez donc son cycle de vie. Cependant, si vous créez des haricots avec le BeanManager, vous avez une poignée sur l'instance de haricots elle-même, et vous pouvez apparemment le détruire explicitement, ce qui, je comprends, signifie qu'il sera GCED.

Mon approche actuelle consiste à créer le bean dans une classe BeanManagerUtil et à renvoyer un objet composite de bean, d'instance et de 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);
    }
}

À partir de cela, dans le code d'appel, je peux alors obtenir l'instance réelle, la mettre dans une carte pour une récupération ultérieure et l'utiliser comme d'habitude:

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

Quand j'en ai fini, je peux rechercher l'emballage destructible et appeler Detrère () dessus, et le haricot et ses personnes à charge doivent être nettoyés:

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

Cependant, après avoir dirigé plusieurs travailleurs et quitté mon jboss (7.1.0.alpha1-snapshot) pendant environ 20 minutes, je peux voir GC se produire

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

Pourtant, un histogramme JMAP montre toujours les anciens ouvriers et leurs instances dépendantes qui traînent, Ungced. Qu'est-ce que je rate?

Grâce à un débogage, je peux voir que le champ de contexte du haricot créé a le contexte du type de travail correct, pas d'installations incomplètes et aucune information parentale. Il a un certain nombre d'immeubles dépendants, qui sont comme attendus des champs sur le travailleur.

L'un de ces champs sur le travailleur est en fait une instance, et lorsque je compare ce champ avec celui d'un travailleur récupéré via la recherche d'instance programmatique, ils ont une composition de création-contexte légèrement différente. Le champ d'instance sur le travailleur recherché via l'instance a le travailleur lui-même sous des instances incomplètes, tandis que le champ d'instance sur le travailleur récupéré du BeanManager ne le fait pas. Ils ont tous deux des entretiens entre les parents et des personnes dépendantes.

Cela me suggère que je n'ai pas reflété correctement la récupération de l'instance. Cela pourrait-il contribuer au manque de destruction?

Enfin, lors du débogage, je peux voir Bean.destroy () être appelé dans mon destructibleBeanInstance.destroy (), et cela passe par ManagedBean.Destroy, et je peux voir des objets dépendants être détruits dans le cadre du .release (). Cependant, ils ne sont toujours pas collectés aux ordures!

Toute aide à ce sujet serait très appréciée! Merci.

Pas de solution correcte

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top