2017-06-13 6 views
0

Java Agent fournit les services requis pour instrumenter le code du langage de programmation Java. ClassFileTransformer est une implémentation pour Java Agent, et la transformation se produit avant que la classe ne soit définie par la JVM. La seule méthode transform est requise pour l'implémentation, et elle est appelée pour chaque nouvelle définition de classe. Une illustration de la façon dont Java Agent œuvres:Comment enregistrer le bytecode java instrumenté par l'agent Java?

Java Agent

Je veux enregistrer le code instrumenté, afin que je puisse exécuter le fichier de classe instrumenté sans instrumenter chaque fois. Comme j'ai vérifié Interface Instrumentation, je n'ai vu aucune API directe pour sauver le bytecode transformé. Je me demande s'il est possible d'utiliser Java Agent pour atteindre mon objectif, ou d'autres outils?

+0

Est-ce que vous instrumentez vos propres classes ou une bibliothèque tierce? – vempo

+0

@vempo mes propres classes, exemples de codes avec le code source disponible. – Qoros

Répondre

1

Ce dont vous avez besoin, c'est d'une instrumentation à la compilation ou à la compilation, pas de l'exécution. La plupart des outils d'instrumentation bytecode prennent en charge les deux - Javassist, AspectJ, ASM.

En fait, vous pouvez enregistrer le bytecode instrumenté par votre agent dans un fichier .class, le résultat étant simplement un tableau d'octets représentant une classe. Cependant, vous devrez exécuter votre programme au moins une fois avec l'agent, et assurez-vous de charger toutes les classes que vous voulez instrumentaliser afin qu'un fichier .class soit créé pour chacune d'elles. Donc Je ne recommande pas cette méthode.

if (shouldInstrument) { 

    CtClass cclass = pool.get(className.replaceAll("/", ".")); 

    // Instrument the class here 

    byte[] bytecode = cclass.toBytecode(); 

    File outputFile = new File(String.format("%s/%s.class", outputDirectory, className)); 
    Files.createDirectories(outputFile.getParentFile().toPath()); 

    try (FileOutputStream fos = new FileOutputStream(outputFile)) { 
     fos.write(bytecode); 
    } 

    return bytecode; 
} 

De plus, si votre objectif est d'ajouter des fonctionnalités à vos propres classes sans polluer le code source avec un code passe-partout, vous pouvez manipuler le code source au lieu du bytecode. Source -> source générée -> bytecode (compiler). Par exemple, en utilisant des annotations et un annotation processor personnalisé.

+0

Merci. Vous avez mentionné sauvegarder le bytecode instrumenté par votre agent dans un fichier '.class'. J'ai essayé, mais j'ai trouvé que la fonction 'transform' était appelée pour chaque classe. J'ai également essayé de sauvegarder tout le code transformé en une classe, mais cela ne fonctionne pas. – Qoros

+0

Je voulais dire que vous ne pouviez utiliser que les classes dont vous aviez besoin et les enregistrer dans les fichiers de classe respectifs. – vempo

+0

Qu'entendez-vous par "classe la plus éloignée"? Parlez-vous des classes internes? Je pense que vous travaillez avec des hypothèses incorrectes ici. Toutes les classes déclarées dans un seul fichier source Java ont chacune leur propre fichier .class. La méthode transform() n'est pas appliquée à un fichier source Java, mais à chaque classe individuelle - les classes sont chargées une à la fois. Essayez d'exécuter mon code et pour les classes internes, vous verrez quelque chose comme Test $ 1.class (anonyme), Test $ Inner.class, Test $ Inner $ Deeper.class etc – vempo