• Java探针技术-如何从asm代码中正确使用Instrumentation.retransformClasses()


      我使用asm库来执行一些Java字节码修改 - 特别是修改我的类来实现一个新的接口和相关的方法。我目前的做法是通过javaagent使用核心asm API。我想保留这种动态方法,而不是静态修改.class文件。 在更高层次上,我的问题是,如果我选择修改从B扩展的类A,我还需要修改B.(鉴于我对如何在JVM中加载类的理解,我相信类B将始终是(如果我错了,请纠正我)假设我假设我需要返回并重新转换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感兴趣。我期待的是我会看到超类(B)的名称被打印在**1**上(但没有变换,因为我没有认为这在第一遍时很有趣),然后,一旦我到达**2**并发现A的超类是B,我应该尝试重新生成B.此时,我期待这个方法再次被调用(通过inst.retransformClasses())和我会看到B在**1**上打印。但是,我没有。 (我已经添加了打印语句,并且确定我正在进行转换呼叫。我还检查了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);
    }
    
  • 相关阅读:
    Ext.js给form加背景图片
    Linux安装Scala
    idea 无法创建Scala class 选项解决办法汇总
    idea 无法创建Scala class 选项解决办法汇总
    i++和++i的区别,及其线程安全问题
    java面试题
    大数据学习——scala入门程序
    大数据学习——spark安装
    大数据学习——kafka+storm+hdfs整合
    大数据学习——日志监控告警系统
  • 原文地址:https://www.cnblogs.com/liboware/p/12494082.html
Copyright © 2020-2023  润新知