일부 Java 바이트 코드 수정을 수행하기 위해 asm 라이브러리를 사용하고 있습니다. 특히 새로운 클래스와 메소드를 구현하기 위해 클래스를 수정해야합니다. 현재 나의 접근 방식은 javaagent를 통해 코어 asm API를 사용하고있다. 정적 인 .class 파일을 수정하는 것과는 반대로이 동적 인 접근 방식을 유지하고 싶습니다.Asm 코드 내에서 Instrumentation.retransformClasses()를 올바르게 사용하려면 어떻게해야합니까?
더 높은 수준에서 내 문제는 B에서 확장되는 A 클래스를 수정하는 경우 B도 수정해야한다는 것입니다. (클래스가 JVM에서로드되는 방식에 대한 내 이해를 감안할 때 클래스 B는 항상 클래스 A가되기 전에 변압기에 건네 질 것입니다. (내가 틀렸다면 수정하십시오.) 그 가정을 감안할 때, 저는 다시 돌아 가야한다고 생각합니다. B. 내 접근 방식은 다음과 같습니다. 코드의 비트 :
public byte[] transform(ClassLoader l, String name, Class<?> clazz, ProtectionDomain d, byte[] b) {
throws IllegalClassFormatException {
// **1**
System.out.println("--->>> " + name);
if (interestingClass(name)) {
try {
ClassReader cr = new ClassReader(b);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
PyClassVisitorAdapter pv = new PyClassVisitorAdapter(cw, name);
cr.accept(pv, 0);
// **2** Retrieve the superclass and try to transform that
if (! "Ljava/lang/Object;".equals(pv.getSuperName())) {
String cName = classJvmToCanonical(pv.getSuperName());
Class[] classes = inst.getAllLoadedClasses();
for (Class c : classes) {
if (c.getName().equals(cName)) {
inst.retransformClasses(c);
break;
}
}
}
// Dump the transformed class
ClassReader cr2 = new ClassReader(cw.toByteArray());
ClassWriter cw2 = new ClassWriter(cr2, 0);
TraceClassVisitor tcv = new TraceClassVisitor(cw2, new PrintWriter(System.out));
cr2.accept(tcv, 0);
return cw2.toByteArray();
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
} else {
return b;
}
}
(
inst
생성자에 전달됩니다
Instrumentation
에 대한 핸들입니다)
내가 힘들게 지내고있는 부분은 **2**
의 설명에 표시된 블록입니다. 다시 A가 B를 확장한다고 가정 해 봅시다. A 변환에 '관심이 있습니다'라고 말하자. 내가 기대하는 것은 **1**
에 수퍼 클래스 (B)의 이름이 인쇄되는 것을 볼 수있다. 첫 번째 단계에서 재미 있다고 생각하면) **2**
에 도착하면 A의 수퍼 클래스가 B라는 것을 알게되면 B를 다시 변환해야합니다.이 시점에서이 메서드가 다시 호출 될 것으로 기대하고 있습니다 (inst.retransformClasses()
통해). 나는 B가 **1**
에 인쇄되는 것을 볼 것입니다. 그러나 나는 그렇지 않습니다. (print 문을 추가하고 retransform 호출에 도달했는지 확인합니다. 또한 Instrumentation.isRetransformClassesSupported()
및 Instrumentation.isModifiableClass(c)
이 모두 true를 반환하는지 확인했습니다).
저는 에이전트를 올바르게 설정했다고 생각합니다. 매니페스트에서 Can-Retransform-Classes 및 Can-Redefine-Classes를 모두 true로 설정합니다. 내가 잘못 여기서 뭘하는지에 관해서는
public static void premain(String agentArgs, Instrumentation inst) {
inst.addTransformer(new PyClassFileTransformer(inst), true);
}
모든 통찰력 : 나는 에이전트의 premain
방법으로 계측에 변압기를 추가 할 때 또한, 나는 이렇게? 감사.
문제가 해결 되었습니까? @Jens 나에게 몇 가지 조언을주고 [여기] (http://stackoverflow.com/questions/18657095/got-unsupportedoperationexception-when-try-to-retransformclasses) 갈 수 있습니까? –