2017-08-10 11 views
0

Je suis un débutant à l'instrumentation ASM et bytecode et essaie d'apprendre avec un exemple simple. Je veux visiter toutes les méthodes de toutes les classes chargées et marquer/imprimer comme méthode visitée.Java ASM ne visite pas toutes les méthodes de mon AdviceAdapter

Ci-joint est mon programme, mais il ne fonctionne pas comme prévu. Seules quelques méthodes de chaque classe chargée sont visitées et le repos est ignoré. Ne semble pas comprendre sur quelle base certains sont visités et certains sont ignorés. Par exemple, lorsque la classe "javax/servlet/http/HttpServlet" est chargée, elle appelle visitMethod uniquement pour les méthodes constructor et doGet et ignore le reste des méthodes.

ASMAgent.java

package com.ag.asm; 

import java.lang.instrument.Instrumentation; 

public class ASMAgent { 
    public static void premain(String agentArgs, Instrumentation inst) { 
     System.out.println("Starting the agent"); 
     inst.addTransformer(new AGClassTransformer()); 
    } 
} 

AGClassTransformer.java

package com.ag.asm; 

import java.lang.instrument.ClassFileTransformer; 
import java.lang.instrument.IllegalClassFormatException; 
import java.security.ProtectionDomain; 

import org.objectweb.asm.ClassReader; 
import org.objectweb.asm.ClassVisitor; 
import org.objectweb.asm.ClassWriter; 

public class AGClassTransformer implements ClassFileTransformer { 
    public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, 
      ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { 
     ClassReader cr = new ClassReader(classfileBuffer); 
     ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES); 
     ClassVisitor cv = new AGMethodClassVisitor(cw, className); 
     cr.accept(cv, 0); 
     return cw.toByteArray(); 
    } 
} 

AGMethodClassVisitor.java

package com.ag.asm; 

import org.objectweb.asm.ClassVisitor; 
import org.objectweb.asm.ClassWriter; 
import org.objectweb.asm.MethodVisitor; 
import org.objectweb.asm.Opcodes; 

public class AGMethodClassVisitor extends ClassVisitor { 
    private String className; 

    public AGMethodClassVisitor(ClassWriter cw, String pClassName) { 
     super(Opcodes.ASM5, cw); 
     className = pClassName; 
    } 

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

    @Override 
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 
     MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); 
     if (mv != null) { 
      mv = new AGMethodAdapter(Opcodes.ASM5, mv, access, name, desc, className); 
      if (className.equalsIgnoreCase("javax/servlet/http/HttpServlet")) { 
       System.out.println("..." + className + ";" + name); 
      } 
     } 
     return mv; 
    } 

    public void visitEnd() { 
     cv.visitEnd(); 
    } 
} 

AGMethodAdapter.java

package com.ag.asm; 

import org.objectweb.asm.MethodVisitor; 
import org.objectweb.asm.Opcodes; 
import org.objectweb.asm.commons.AdviceAdapter; 

public class AGMethodAdapter extends AdviceAdapter { 

    private String className; 
    private String methodName; 
    private boolean isProtected; 

    public AGMethodAdapter(int api, MethodVisitor mv, int access, String name, String desc, String className) { 
     super(api, mv, access, name, desc); 
     this.methodName = name; 
     this.className = className; 
     this.isProtected = (access & Opcodes.ACC_PROTECTED) != 0; 
    } 

    @Override 
    protected void onMethodEnter() { 
     // mark method as entered 
    } 

    @Override 
    protected void onMethodExit(int opcode) { 
     // mark method as exited 
    } 
} 

Ici un point à noter est que si je supprime AGMethodAdapter.java en tant qu'adaptateur personnalisé de visitMethod de AGMethodClassVisitor.java et retourne juste ce qui est retourné de super classe, tout fonctionne bien. Je ne comprends pas pourquoi AGMethodAdapter.java n'autorise pas certaines méthodes à visiter.

Toute aide est grandement appréciée.

+0

Il est difficile de croire qu'ASM décide de ne pas invoquer 'visitMethod' en fonction de ce que vous retournerez * dans * cette méthode, car cela nécessiterait une précognition. Comment déterminez-vous que la méthode n'a pas été appelée? – Holger

Répondre

0

Essayez

cr.accept(cv, ClassReader.EXPAND_FRAMES); 

au lieu de

cr.accept(cv, 0); 

Exception est pas jeté de l'agent java, donc vous n'êtes pas en mesure de voir que IllegalArgumentException est levée.