2016-02-10 1 views
2

Disons que je classe comme ceci:Quand VisitMethod d'un ClassVisitor sera appelé dans asm?

public class ClassPrinter extends ClassVisitor { 


    public ClassPrinter(ClassWriter writer) { 
     super(Opcodes.ASM5, writer); 
    } 

    @Override 
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 
     super.visit(version, access, name, signature, superName, interfaces); 
    } 

    @Override 
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 
     // when this line will get executed? 
     System.out.println(name); 
    } 

} 

maintenant quand le visitMethod sera appelé? Est-ce quand le chargement de classes se passe en Java (c'est-à-dire quand le visiteur de classe est appelé?) Ou quand une méthode est appelée sur l'objet de classe?

Je suis confus à ce sujet.

Répondre

2

visitMethod est appelée lorsque vous appelez directement ou indirectement le visiteur. Ceci est totalement indépendant du chargement ou de l'exécution de la classe dans la JVM.

ASM utilise le modèle de visiteur. Vous passez dans une classe implémentant les rappels qui vous intéressent, puis vous passez à quelque chose comme ClassNode.accept(cv) et le ClassNode appellera automatiquement tous vos callbacks pour les parties appropriées du classfile.

+0

Merci Animony. J'ai encore quelques questions, disons que j'utilise le code ci-dessus pour construire un agent java et le charger au démarrage de mon application. Puis, lors de l'exécution de mon application, tous les noms de méthode seront-ils imprimés via visitMethod? Par exemple, disons que dans mon application il y a un appel de méthode 'a.test()' alors j'obtiendrai la méthode de test et ses appels de méthode correspondants seront-ils tracés? –

+0

@ Ant's: ** Non **, ce visiteur est pour le traitement d'une * classe *, pas pour tracer une * exécution *. Lorsque vous voulez vraiment entrer dans un tel sujet comme la manipulation du code octet, vous devriez arrêter de baser votre programmation sur des devinettes. Commencez à lire la documentation où l'objectif de la bibliothèque est expliqué, avant même de regarder l'API ... – Holger

0

Normalement, vous enchaînez un ClassVisitor comme ça à un ClassReader, qui lit une classe donnée et déclenche toutes visit* méthodes

ClassReader cr = new ClassReader(className); 
cr.accept(new ClassPrinter(), 0); 

Lorsque vous voulez lire la classe (et imprimer le nom de la méthode) est totalement à toi.

Si toutefois vous voulez transformer une classe et le charger à la machine virtuelle Java, une possibilité est de sous-classe ClassLoader, où vous lisez la classe, la transformer (en utilisant visit* méthodes), et écrire avec ClassWriter. Voir le dossier examples de l'ASM (par exemple Annotations.java) à partir de certains exemples de code.