So, with the code written below, my output is:
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
which is puzzling me. Why would my methodVisitor
be null
? The ASM source code seems to only return null
for the methodVisitor
when the classVisitor
is null
, which is not true in my case.
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;
}
}
EDIT:
I call this code like this:
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;
}
Aucun commentaire:
Enregistrer un commentaire