2016-09-29 1 views
1

J'utilise l'injection de dépendance (DI) dans une application RCP Eclipse. J'ai beaucoup de classes qui effectuent un code similaire à ci-dessous:Memory Leak/ContextInjectionFactory/IEclipseContext

public class SomeClass { 
    @Inject 
    private IEclipseContext context; 

    private SomeObject void someMethod(){ 
     SomeObject someObject = 
      ContextInjectionFactory.make(SomeObject.class, context); 
     // Do stuff with someObject 
    } 
} 

Lorsque je contrôle l'application à l'aide jvisualvm, je remarque qu'il ya une fuite de mémoire à cause de cela. L'objet EclipseContext ne cesse de croître jusqu'à ce qu'il finisse par manquer de mémoire.

Si je fais ce qui suit, la fuite de mémoire en va:

public class SomeClass { 
    @Inject 
    private IEclipseContext context; 

    private SomeObject void someMethod(){ 
     IEclipseContext childContext = context.createChild(); 
     SomeObject someObject = 
      ContextInjectionFactory.make(SomeObject.class, childContext); 
     childContext.dispose(); 
     // Do stuff with someObject 
    } 
} 

Je ne l'ai pas vu tous les documents qui prend en charge de faire ma solution de contournement. Existe-t-il des effets secondaires négatifs pour disposer de childContext après la création de la classe? Y a-t-il une meilleure approche globale en utilisant CIF que je n'ai pas rencontré?

Pour ce que ça vaut, mon code a beaucoup de classes, dont certaines sont annotées avec @Singleton/@Creatable. Je ne suis pas sûr si ceux-ci seraient effectués par un contexte de parent disposé.

Merci!

+0

Je n'ai vu aucun rapport de fuite et je n'ai pas vu cela dans mon code. –

+0

Ouais c'est vraiment étrange. La seule différence dans mon code est ce qui est montré ci-dessus. Je crée beaucoup d'objets dont la plupart sont détruits quand ils ne sont plus nécessaires. Au cours de quelques jours, je remarque qu'il y a des millions de références d'objets dans le contexte principal et ça grandit jusqu'à ce que j'obtienne une erreur de mémoire. Si je fais la solution, tout va bien. Connaissez-vous un impact négatif en utilisant la solution de contournement? – ekjcfn3902039

+0

Si quelque chose que vous faites avec le contexte enfant injecte IEclipeContext, il finira par accéder à un contexte éliminé s'il tente d'y accéder plus tard. Cela donne des erreurs de débogage difficiles. Savez-vous quel champ de la classe EclipseContext stocke toutes ces références? –

Répondre

2

Lorsque vous utilisez l'injection pour définir des champs dans votre classe comme ceci:

public class Test 
{ 
    @Inject 
    private StatusReporter rep; 
    @Inject 
    private IEventBroker broker; 


    public Test() 
    { 
    } 
} 

Eclipse doit suivre chaque champ qui a été injecté afin qu'il puisse réinjecter le champ si la valeur dans le contexte change Eclipse. Cela implique la création d'objets TrackableComputationEx‌​t et ‌​ContextInjectionList‌​ener pour chaque champ injecté.

Si au contraire vous injectez les valeurs dans le constructeur comme ceci:

public class Test 
{ 
    private StatusReporter rep; 
    private IEventBroker broker; 

    @Inject 
    public Test(StatusReporter rep, IEventBroker broker) 
    { 
    this.rep = rep; 
    this.broker = broker; 
    } 
} 

Eclipse n'a pas besoin de suivre l'injection Constructor si ces objets ne sont pas créés (mais vous n'aurez pas mises à jour si le contexte les valeurs sont modifiées).

En testant cela, il semble toujours qu'un objet de suivi d'utilisation interne ait été créé.

+0

C'est étrange que personne d'autre n'ait mentionné la même chose que moi depuis que je vois beaucoup de code en utilisant des injections de champ par rapport aux injections de constructeurs. Est-ce que les objets de suivi disparaissent après que la classe n'est plus utilisée? Si j'ai un objet Collection et efface la collection, les références de suivi disparaissent-elles? Je devine (par le nombre de cas que j'ai vus) qu'avec des injections sur le terrain, ils ne le font pas (même si je m'y attendais) – ekjcfn3902039

+0

Eh bien Java n'a pas de moyen de suivre quand quelque chose «disparaît» (à moins qu'il y ait quelques WeakReferences quelque part j'ai manqué) donc probablement pas. Ils traînent probablement jusqu'à ce que le contexte soit éliminé. Mais ce code est très complexe et difficile à lire (comme d'habitude). Je pense que la plupart des gens n'utilisent l'injection que sur un nombre limité d'objets de l'interface utilisateur. –