나는 컴파일러 프로젝트를위한 ASM API를 배우기 시작했다. 자바 에이전트 개발을 위해 Java Instrumentation과 ASM ByteCode Library를 사용하고 있습니다.서버를 시작한 후 런타임에 className과 methodName을 ASM 파서의 ClassVisitor() 및 methodVisitor()에 전달할 수 있습니까?
속성을 통해 클래스 이름과 메소드 이름을 전달 중입니다. 내 목표는 런타임에 className과 methodName을 변경하는 것입니다. 이는 서버를 시작한 후 또는 premain()을 호출 한 후이를 의미합니다.
하지만 className 또는 packageName이 시작된 서버 전에 전달 된 항목에 대해서만 작동합니다.
나는 javaagent (premain())를 호출하는 동안 주어진 pakage/class에 대한 메소드에 대해 ASM set visitor를 이해한다.
서버가 시작되거나 premain()이 호출 된 후에도 특정 클래스와 메서드를 방문하려고했습니다.
매우 도움이 될 것입니다.
이것은 현재 실행중인 프로그램입니다.
public class AddPrintlnAgent implements ClassFileTransformer {
public static void premain(String agentArgs, Instrumentation inst) {
Properties prop = new Properties();
try {
prop.load(new FileInputStream("C:\\locator.properties"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
inst.addTransformer(new AddPrintlnAgent());
}
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
byte[] retVal = null;
if (className.equals(className)) {
ClassWriter cw = new ClassWriter(0);
ClassVisitor ca = new MyClassAdapter(cw);
ClassReader cr = new ClassReader(classfileBuffer);
cr.accept(ca, 0);
retVal = cw.toByteArray();
}
return retVal;
}
public class MyClassAdapter extends ClassNode implements Opcodes {
private ClassVisitor cv;
Properties prop = new Properties();
public MyClassAdapter(ClassVisitor cv) {
this.cv = cv;
}
@Override
public void visitEnd() {
try {
prop.load(new FileInputStream("C:\\locator.properties"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
for (MethodNode mn : (List<MethodNode>) methods) {
if (mn.name.equals(prop.getProperty("methodName").trim())) {
InsnList il = new InsnList();
il.add(new FieldInsnNode(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"));
il.add(new LdcInsnNode(prop.getProperty("message")));
il.add(new MethodInsnNode(INVOKEVIRTUAL, "java/io/PrintStream",
"println", "(Ljava/lang/String;)V"));
mn.instructions.insert(il);
mn.maxStack +=2;
}
}
accept(cv);
}
}
} 사전에
감사
사티시 V J 당신은 정리 코드를해야
내가 틀렸다고 정정하되'if (className.equals (className)) {'는 항상 true를 반환해야하므로 모든 클래스에 대해 바이트 코드를 다시 작성해야합니다. 또한 "className과 methodName을 변경하십시오"라는 것이 정확히 무엇을 의미합니까? 특정 클래스와 메소드의 이름을 변경하려고하십니까? – vijay