Jen*_*ens 8 java bytecode java-bytecode-asm
我正在使用asm库来执行一些Java字节码修改 - 专门用于修改我的类以实现新的接口和相关方法.我目前的方法是通过javaagent使用核心asm API.我想保留这种动态方法,而不是静态修改.class文件.
在更高的层次上,我的问题是,如果我选择修改从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;
}
}
Run Code Online (Sandbox Code Playgroud)
(inst是Instrumentation在构造函数中传入的句柄)
我正在努力的部分是在评论中标记的块**2**.让我们再说一次A扩展B并且我'感兴趣'转换A.我期待的是我会看到超级(B)的名字被打印出来**1**(但是没有被改变因为我不认为它在第一次传递时很有意思)然后,一旦我**2**发现A的超类是B,我应该尝试重新转换B.此时我希望再次调用此方法(via inst.retransformClasses())并且我会见B打印出来**1**.但是,我没有.(我已经添加了print语句,并且我确定我正在接收转换调用.我也检查了它Instrumentation.isRetransformClassesSupported()并且Instrumentation.isModifiableClass(c)都返回true).
我相信我已经正确设置了代理商; 在清单中将Can-Retransform-Classes和Can-Redefine-Classes设置为true.此外,当我在代理的premain方法中将变换器添加到Instrumentation时,我这样做:
public static void premain(String agentArgs, Instrumentation inst) {
inst.addTransformer(new PyClassFileTransformer(inst), true);
}
Run Code Online (Sandbox Code Playgroud)
关于我在这里做错了什么见解?谢谢.
您可以更改字节码检测策略,因此当加载类 B 时,您会找到它的所有子类,并在此时决定是否需要立即修改类 B。这可以通过维护类元数据存储库或内存中的缓存(即有关类层次结构的信息)来优化,这样您就不必每次都加载元数据。
| 归档时间: |
|
| 查看次数: |
1506 次 |
| 最近记录: |