2010-11-23 44 views
1

J'ai un dossier avec beaucoup de fichiers .class. Ces classes sont mises à jour à partir de 'app 1'. Et il y a 'app 2' qui charge ces classes dinamiquement.tomcat - reload classes dynamiquement

Et le problème est ....

'app 2' utilise un fichier de classe, 'app 1' mise à jour ce fichier, puis 'app 2' a besoin à nouveau la classe mais semble garder et utiliser une copie de la classe plus ancienne.

donc, j'ai vérifié le dossier et la classe a été mise à jour avec succès, j'ai essayé de recharger 'app 2' mais il continue à utiliser l'ancienne classe.

Uniquement si je redémarre tomcat 'app 2' lit la nouvelle classe.

Pourquoi est-ce? Je suis autorisé à recharger 'app 2' mais, dans l'environnement de production, je ne peux pas redémarrer tomcat.

Il est très important dans mon travail, j'apprécie une idée .....

J'utilise une nouvelle installation de tomcat6 et je charger les fichiers de classe avec: Class.forName(<classname>).newInstance()

thx beaucoup

Répondre

0

Je pense que vous devriez essayer de séparer les classes pour ces 2 applications. Essayez d'abord de créer 2 répertoires identiques. Un pour app1, second pour app2. Si cela résout votre problème emballez vos classes dans le pot et ne gardez que 2 fichiers jar en double. Je pense que le problème n'est pas en Java mais dans le système de fichiers. Je crois que vous utilisez Windows. Si c'est probablement le cas, essayez de faire ce que vous faites maintenant sous Linux (à moins que cela ne soit pas pertinent pour votre entreprise).

3

Le problème est que le moteur d'exécution a déjà chargé l'ancien classfile dans le chargeur de classe utilisé par le code qui veut utiliser la classe modifiée. Vous devrez trouver un moyen d'obtenir le classloader pour actualiser son contenu de classe à partir du disque afin d'obtenir ce que vous voulez. C'est pourquoi Class.forName() ne fonctionne pas: il accède à la version déjà chargée (et mise en cache) de la classe. Alex R a raison de dire que vous devriez essayer de restructurer votre code pour séparer vos classes pour ces deux projets. Mais, si vous êtes décidé à recharger cette classe et à garder les choses telles qu'elles sont, vous pouvez essayer Classloader.defineClass() et charger la nouvelle version de la classe de son fichier .class dans un byte [] , puis en passant ce byte [] à Classloader.defineClass(). Vous voudrez probablement utiliser le chargeur de classe de contexte associé à votre application par Tomcat (plutôt que par le chargeur de classe Tomcat de niveau supérieur). Une documentation distingue les deux dans la documentation du projet Tomcat.

1

Le comportement par défaut est que les classes sont mises en cache par le ClassLoader qui les a chargées. Si vous le faites: Class.forName('MyClass') deux fois de suite, vous ne chargerez la classe que la première fois.

Pour recharger une classe, vous devez non seulement libérer toute référence que vous avez déjà à une instance de cette classe, mais également toute référence au ClassLoader qui l'a chargée. C'est seulement alors que vous pouvez être sûr que toute la classe peut être collectée (ou vous allez vous retrouver avec des fuites de mémoire - un problème récurrent dans le rechargement de webapps).

Vous pouvez pouvez étendre ClassLoader et modifier le comportement de mise en cache.

+0

Salut, Im va essayer cela, mais, pensez-vous comment pourrais-je modifier le comportement de la mise en cache? – david