2009-08-08 4 views
3

J'ai un agent java qui instruments bytecode. J'utilise l'API de java 6 pour permettre aux utilisateurs de charger dynamiquement l'agent et le code d'instrument et de deinstrument en utilisant mon agent java. J'utilise l'attribut de manifeste Boot-Class-Path pour m'assurer que mes classes javagent sont dans le chemin de classe de démarrage afin que mes utilisateurs puissent instrumenter des classes telles que ArrayList, etcJavaagent classe déchargement

Cependant, le problème vient du versionnage. Supposons qu'un utilisateur attache dynamiquement la version 1 de mon agent. Puis je lui ai donné la version 2. Maintenant que son serveur d'applications ne s'est jamais arrêté depuis qu'il a attaché la version 1 de mon agent, les classes de la version 1 sont toujours chargées.

J'ai besoin d'un moyen tel que lorsque la version 2 de mon client javaagent, la version 1 est déchargée.

Je sais que l'une des façons serait d'écrire un classloader client pour les classes de mon javaagent, et de définir la référence du classloader sur null. Cependant, dans ce cas, je ne pourrai pas classer les classes dans le classpath boot puisque mon classloader sera dans la hiérarchie du classloader de démarrage et donc mes utilisateurs ne peuvent pas classer des classes comme ArrayList car j'ajoute un appel dans ArrayList méthodes de classes de mon agent le chargeur de classe de démarrage ne sera pas en mesure de les voir.

Alors, existe-t-il un moyen de résoudre le problème du chemin d'accès au démarrage et de toujours décharger les classes de l'agent précédent?

+1

Vous pourriez jeter un oeil à JavaRebel (http://www.zeroturnaround.com/javarebel/), qui est une implémentation commerciale de ce que vous essayez de faire. Cela pourrait vous donner une indication de ce qui est ou n'est pas possible. – skaffman

Répondre

1

Je ne suis pas un expert sur ce sujet, mais il semble que ce genre de déchargement-à-remplacer n'est pas directement pris en charge.

Mais avez-vous besoin de décharger-remplacer la classe? Pourriez-vous créer à la place une classe sans cesse changeante à laquelle le monde extérieur s'adresse, dans laquelle vous appliquez en interne un système de gestion de version? Par exemple, vous créez une classe MyToolAgent qui a, disons, une chaîne statique avec le nom de classe de ToolAgentImplementation à utiliser. Lors de la première publication, il est configuré pour utiliser ToolAgentImplementation1_0. Lorsque vous effectuez une mise à niveau vers la version 2.0, vous déployez une classe supplémentaire appelée ToolAgentImplmenetation2_0 et mettez à jour la classe MyToolAgent pour la charger et l'utiliser. Vous ne déchargez jamais la version 1.0, mais vous arrêtez de l'utiliser. Vous perdez de la mémoire ici, mais vous obtenez la mise à niveau de la version. Je ne sais pas si cela est faisable dans votre situation, mais en général, il semble que la JVM ne supporte pas l'échange direct dans une nouvelle version, mais que vous devriez pouvoir la cacher d'une manière ou d'une autre.

0

Je ne suis pas sûr que cela fonctionnera, mais il peut vous donner quelques options ...

Au lieu d'essayer de recharger l'agent actuel (appelons-ce l'agent de l'outil), ajouter un nouvel agent (un agent d'installation). L'agent d'installation aurait exactement une fonction: utilisez RedefineClasses() pour remplacer les classes d'agent d'outil d'origine. Si vous nommez l'agent d'installation avec un numéro de version dans le nom de classe (MyToolInstallerV1), vous pouvez continuer à charger de nouveaux programmes d'installation qui mettent à jour l'agent d'outil. Si la taille devient un problème, un agent d'installation peut peut-être rechercher des installeurs antérieurs et remplacer leurs classes par un petit talon sans opération.

0

Je n'ai rien instrumenté pour l'instant mais je joue juste avec java.util.ServiceLoader et j'ai implémenté une sorte d'architecture de plugin, avec un chargement dynamique de JAR avec l'approche de votre URLClassLoader.Je ne sais pas si l'instrumentation pourrait être modifiée de cette façon, mais les problèmes de version et de chargement/déchargement dynamique peuvent être détectés, et c'est très rapide à tester parce que le matériel est fait par le ServiceLoader (suivez simplement la spécification minuscule/META-INF/services/XXX) et vous êtes prêt :)

Cordialement.

0

Cas d'utilisation parfait pour OSGI. Vous ne savez pas si vous pouvez brancher votre agent en tant que groupe.

Questions connexes