Ниже приведен способ добавления дополнительных полей в класс, например «int i = 10;». Предполагая, что вы используете javaagent для выполнения инструментария: 1) Используйте следующий класс в качестве основного класса java-агента.
import java.lang.instrument.Instrumentation;
public class SimpleAgent {
public static void premain(String agentArgs, Instrumentation inst) {
ClassTransformer transformer = new ClassTransformer();
inst.addTransformer(transformer);
}
}
2) addTransformer вызывает метод преобразования класса ClassTransformer, который определяется следующим образом
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
public class ClassTransformer implements ClassFileTransformer{
public byte[] transform(ClassLoader loader,
String className,
Class classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] b)
throws IllegalClassFormatException {
try
{
ClassReader cr=new ClassReader(b);
ClassWriter cw = new ClassWriter(cr,ClassWriter.COMPUTE_MAXS);
AddField cp = new AddField(cw);
cr.accept(cp,0);
return cw.toByteArray();
}
catch(Exception e)
{
System.out.println(e);
}
return b;
}
}
3) наконец, AddField, который выглядит следующим образом, является ClassVisitor, который отвечает за добавление нового поля в класс
import static org.objectweb.asm.Opcodes.ASM4;
import org.objectweb.asm.ClassVisitor;
class AddField extends ClassVisitor{
static String className;
static String methName, descrip;
public AddField(ClassVisitor cv) {
super(ASM4, cv);
}
@Override
public void visit(int version, int access, String name,
String signature, String superName, String[] interfaces) {
className = name;
cv.visit(version, access, name, signature, superName, interfaces);
}
public void visitEnd() {
cv.visitField(0, "i", "I", null , new Integer(10));
cv.visitEnd();
}
}
4. ** NEW EDIT ** для добавления переменной в метод. Переменная должна быть сохранена во временной переменной, и ее можно будет использовать позже. Для этой цели можно использовать следующий адаптер (см. OnMethodEnter):
import static org.objectweb.asm.Opcodes.ASM4;
import static org.objectweb.asm.Opcodes.*;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.commons.AdviceAdapter;
public class MethodAdapter extends ClassVisitor {
public MethodAdapter(ClassVisitor cv) {
super(ASM4, cv);
}
@Override
public void visit(int version, int access, String name,
String signature, String superName, String[] interfaces) {
cv.visit(version, access, name, signature, superName, interfaces);
}
public MethodVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
MethodVisitor mv;
mv = cv.visitMethod(access, name, desc, signature, exceptions);
mv = new AddVariableAdapter(access, name, desc, mv);
return mv;
}
public void visitEnd() {
cv.visitEnd();
}
public class AddVariableAdapter extends AdviceAdapter{
public AddCallAdapter(int access, String name, String desc,
MethodVisitor mv) {
super(ASM4, mv, access, name, desc);
}
protected void onMethodEnter() {
mv.visitIntInsn(BIPUSH, 10); // pushes the number 10 on to the stack
mv.visitVarInsn(ISTORE, 1); // pops the top of the stack into a local variable indexed by 1
/* code to print the local variable
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitVarInsn(ILOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V");*/
}
}
}
person
sri91
schedule
19.02.2015