[英]Java bytecode instrumentation using ASM, MethodVisitor is null
因此,使用下面的代碼,我的輸出是:
Starting application with the Agent
Visiting class: HelloWorld
Class Major Version: 51
Super class: java/lang/Object
Source: HelloWorld.java
Method: <init> desc = ()V cv = com.amir.agent.instrumentor.amirClassVisitor$1@79f1d448 and mv = null
Method: main desc = ([Ljava/lang/String;)V cv = com.amir.agent.instrumentor.amirClassVisitor$1@79f1d448 and mv = null
Method: foo desc = ()V cv = com.amir.agent.instrumentor.amirClassVisitor$1@79f1d448 and mv = null
Method ends here
Done instrumenting: HelloWorld
這讓我感到困惑。 為什么我的methodVisitor
為null
? 當classVisitor
為null
,ASM源代碼似乎僅對methodVisitor
返回null
,在我的情況下不正確。
package com.amir.agent.instrumentor;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class amirClassVisitor {
private byte[] outData = null;
public amirClassVisitor() {
}
public void performInstrumentation(final String className,
final byte[] classAsBytes) {
final ClassVisitor cl = new ClassVisitor(Opcodes.ASM4) {
@Override
public void visit(final int version,
final int access,
final String name,
final String signature,
final String superName,
final String[] interfaces) {
System.out.println("Visiting class: "+name);
System.out.println("Class Major Version: "+version);
System.out.println("Super class: " + superName);
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public void visitOuterClass(final String owner,
final String name,
final String desc) {
System.out.println("Outer class: "+owner);
super.visitOuterClass(owner, name, desc);
}
@Override
public AnnotationVisitor visitAnnotation(final String desc,
final boolean visible) {
System.out.println("Annotation: "+desc);
return super.visitAnnotation(desc, visible);
}
@Override
public void visitAttribute(final Attribute attr) {
System.out.println("Class Attribute: " + attr.type);
super.visitAttribute(attr);
}
@Override
public void visitInnerClass(final String name,
final String outerName,
final String innerName,
final int access) {
System.out.println("Inner Class: " + innerName + " defined in " + outerName);
super.visitInnerClass(name, outerName, innerName, access);
}
@Override
public FieldVisitor visitField(final int access,
final String name,
final String desc,
final String signature,
final Object value) {
System.out.println("Field: "+name+" "+desc+" value:"+value);
return super.visitField(access, name, desc, signature, value);
}
@Override
public void visitEnd() {
System.out.println("Method ends here");
super.visitEnd();
}
@Override
public MethodVisitor visitMethod(final int access,
final String name,
final String desc,
final String signature,
final String[] exceptions) {
final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
System.out.println("Method: " +name+ " desc = " +desc+ " cv = " +this+ " and mv = " +mv);
return mv;
}
@Override
public void visitSource(final String source,
final String debug) {
System.out.println("Source: "+source);
super.visitSource(source, debug);
}
};
final ClassReader classReader = new ClassReader(classAsBytes);
classReader.accept(cl, 0);
System.out.println("Done instrumenting: " +className);
}
public byte[] result() {
return outData;
}
}
編輯:
我將這樣的代碼稱為:
public class ClassLoadInterceptor implements ClassFileTransformer {
@SuppressWarnings("unchecked")
public byte[] transform(final java.lang.ClassLoader loader,
final java.lang.String className,
final java.lang.Class classBeingRedefined,
final java.security.ProtectionDomain protectionDomain,
final byte[] classfileBuffer) throws IllegalClassFormatException {
if (!(className.startsWith("java") || className.startsWith("sun") || className.startsWith("com/workday/agent"))) {
WorkdayClassVisitor v = new WorkdayClassVisitor();
v.performInstrumentation(className, classfileBuffer);
System.out.println("\t Instrumenting : " +className);
byte[] instrumented_class = v.result();
writeOutClassFile("debug", className + ".class", classfileBuffer);
writeOutClassFile("debug", className + "_instrumented" + ".class", instrumented_class);
return instrumented_class;
}
return classfileBuffer;
}
你打印出來是不是“我的methodVisitor
”,但被返回的值super
的調用visitMethod
,換句話說返回的默認值ClassVisitor.visitMethod
:
返回值 :
一個對象,用於訪問方法的字節碼;如果該類訪問者對訪問此方法的代碼不感興趣,則返回null
。
由於抽象類ClassVisitor
不執行任何操作,因此對訪問該方法沒有興趣,因此null
是理想的返回值。
因此,由您決定實例化一個新的MethodVisitor
實現所需的行為。 或者,由於您似乎打算插入一個類,因此讓您的類訪問者委托給您傳遞給超類構造函數的ClassWriter
。 這樣,您將繼承可以自定義的復制行為。 然后, super.visitMethod
將返回一個非null
方法訪問者,該訪問者將復制該方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.