2012-02-16 2 views
2

EDIT:CORBA + Tomcat 6 + Webapp classloader fuite

J'ai trouvé fuite classloader dans mon webapplication. Cela se résume à une bibliothèque tierce qui initialise CORBA via le service de nommage COS de JNDI et n'expose pas un appel à fermer proprement le contexte de JNDI. Cela laisse des threads liés à CORBA et d'autres ressources référençant mon chargeur de classe webapp et l'empêchant d'être récupéré. Cela entraîne une erreur OutOfMemory: PermGen après quelques redéployages/rechargements.

Pour l'instant j'ai augmenté la mémoire PermGen dans JVM et cela rend les intervalles entre les arrêts du serveur plus longs. Ce n'est évidemment pas une solution mais une solution de contournement (et une mauvaise d'ailleurs).

Je suppose que ma question est de savoir s'il est possible de fermer proprement le contexte JNDI sans tenir de référence. Mon instinct me dit non, mais peut-être que je ne connais pas une caractéristique magique de JNDI qui me permettrait de saisir ce contexte.

Ainsi, la façon dont la bibliothèque 3ème partie initialise objets CORBA est quelque chose le long de ces lignes (gestion des exceptions et d'autres détails entendue rectifier par souci de concision):

private CorbaObjectAggregate initCorba() { 
    InitialContext ctx = null; 
    CorbaObjectAggregate corbaObjects = new CorbaObjectAggregate(); 
    ORB orb = null; 
    Properties env = getContextEnvironment(); 
    String[] args = null; 
    orb = ORB.init(args, null); 
    env.put("java.naming.corba.orb", orb); 
    ctx = new InitialContext(env); 
    //a bunch of object lookups follow 
    corbaObjects.someCorbaObjectReference = (SomeCorbaObjectClass) ctx.lookup("somePaht"); 
    return corbaObjects; 
} 

Ainsi, la référence à ctx est parti après cette méthode fin de l'exécution.

J'ai essayé d'arrêter les filets manuellement mais cela n'a pas permis de réparer la fuite. Je suppose qu'il y a d'autres ressources de corba sur classloader. Je suppose que je pourrais essayer de les traquer dans une méthode de nettoyage et libérer le classloader de cette façon, mais j'espérais une solution plus propre. Pour plus de clarté, la bibliothèque 3rd Party est fermée et je ne peux pas vraiment le changer. Ce n'est pas non plus une option viable pour obtenir de l'aide de la part de l'entreprise.

+0

* (c'est pas une réponse, d'où le commentaire) * ... Personnellement, je demanderais au développeur de l'API tierce pour réparer leur gâchis. En attendant, vous pouvez * atténuer * le problème en utilisant un PermGen plus grand ou en utilisant une JVM qui ne serait pas une Oracle/Sun, car PermGen, IIRC, est une spécificité Oracle/Sun. * (qui dit oh les souvenirs: je me souviens avoir découvert par moi-même un terrible problème de Tomcat + Sun JVM + Hibernate permgen à l'époque où pratiquement aucune information ne pouvait être trouvée sur le sujet;) * À l'époque nous "réparions" notre problème Résine IIRC (il y a vraiment plusieurs années). – TacticalCoder

+0

Malheureusement, les développeurs tiers n'existent pas :). C'est un système hérité avec lequel notre application doit s'intégrer. Mais cela mis à part, je ne suis pas sûr que le problème se trouve directement dans la bibliothèque. Comme je l'ai mentionné, le thread est en fait créé par le sous-système CORBA, donc j'imagine que toute bibliothèque utilisant CORBA déclencherait la création de ce thread. Cela dit, je ne suis en aucun cas un expert de la CORBa. Malheureusement, changer de serveur d'application est non-non non plus. – artur

+1

comme une solution de contournement qui peut vous faire gagner du temps, vous pouvez passer la JVM Oracle/SUn l'argument qui crée un plus grand PermGen ... Quelque chose comme ceci: -XX: MaxPermSize = 512m C'est bien sûr une solution de contournement temporaire. Qu'en est-il de l'option "Find Leaks" de Tomcat 6 * (vous pouvez l'appeler par exemple dans la webapp du gestionnaire Tomcat), trouve-t-elle la même fuite? – TacticalCoder

Répondre

1

Cela va être difficile à réparer. Il y a probablement deux problèmes: - classes chargées à partir du fichier JAR contenant une référence au chargeur de classe d'application Web - les threads démarrés par ce processus ayant le chargeur de classe d'application Web comme chargeur de classe de contexte.

Quelque chose le long des lignes suivantes devrait aider:

  1. Déplacez le JAR CATALINA_BASE $/lib. Cela signifie que les classes sont chargées par le chargeur de classe commun. L'inconvénient est qu'ils sont également visibles et partagés par chaque application Web.

  2. Découvrez où dans votre application l'initialisation est déclenchée. Avant que ce code s'exécute, définissez le chargeur de classe de contexte de thread sur le chargeur de classe système (ou le parent du chargeur de classe actuel (application Web)) et réinitialisez le chargeur de classe de contexte de thread après l'appel init. Cela signifie que les threads créés ne disposent pas du chargeur de classes de l'application Web en tant que chargeur de classe de contexte.

Si les threads sont créés à d'autres moments, la résolution de ces problèmes peut être très difficile.

Pour des renseignements généraux qui peuvent aider à comprendre ce qui se passe, voir: http://people.apache.org/~markt/presentations/2010-11-04-Memory-Leaks-60mins.pdf

Pour voir le genre de chose Tomcat ne interne pour travailler autour de ces questions, voir: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java?view=annotate

+0

+1 pour une réponse très informative. Oui, j'envisageais de déplacer le pot au niveau du conteneur, mais, aussi improbable que cela puisse paraître, j'ai réussi à atteindre les gens derrière le code et après de nombreux emails après avoir reconnu le bogue dans leur code, donc j'espère que CA devrait etre. Votre PDF est une excellente lecture et renforce ce que j'ai compris de diverses sources lors de l'enquête sur la question. La deuxième option que vous avez donnée est intéressante, même si elle ressemble vraiment au dernier recours, c'est-à-dire. dirty hack;) – artur

+0

Je pense que je peux aussi bien le signaler comme une réponse acceptée. C'est effrayant combien de bibliothèques peuvent causer le problème et il est intéressant de savoir quelles mesures sont prises au niveau du conteneur pour se prémunir contre eux. Merci beaucoup pour ta réponse. – artur