Java代理程序:不为所有类调用transform()

时间:2017-08-15 01:22:44

标签: transform instrumentation

我有一个非常简单的变压器:

import java.io.ByteArrayInputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

//this class will be registered with instrumentation agent
public class PizzaTransformer implements ClassFileTransformer {

    public byte[] transform(ClassLoader loader, 
                            String className,
                            Class classBeingRedefined,
                            ProtectionDomain protectionDomain,
                            byte[] classfileBuffer) throws 
    IllegalClassFormatException {
        byte[] byteCode = classfileBuffer;

        System.out.println("This class is  "+className);

        return byteCode;
        }
}

代理商代码如下:

import java.lang.instrument.Instrumentation;

public class PizzaAgent {
    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("Executing premain.........");
        inst.addTransformer(new PizzaTransformer(),true);
    }
}

清单是:

Boot-Class-Path:javassist.jar

Premain-Class:PizzaAgent

Can-Redefine-Classes:true

Can-Retransform-Classes:true

令人费解的是,只有4000多个类被transform()打印出来,当报告19000多个类加载时,通过启用-verbose:class命令行启动。

为什么超过10000个类没有调用transform()?

谢谢

2 个答案:

答案 0 :(得分:0)

在附加代理时,您只看到尚未加载的类。如果要处理已加载的类,则必须显式重新转换这些类。你可以这样做:

instrumentation.retransformClasses(instrumentation.getLoadedClasses());

但是,某些类不可重新转换(Instrumentation::isModifiable),您很可能需要拆分数组以避免耗尽内存。

答案 1 :(得分:0)

可能有两种情况,

  1. 类尚未由JVM加载

    如果JVM尚未加载任何类,则有可能不会为该类调用Java agent:transform()。

    每当由JVM Java代理加载时,都会为该类调用transform()。

  2. 在初始化ClassFileTransformer之前加载类

    如果您在ClassFileTransformer实现中使用了任何类或任何其他Agent类,则该类可能在ClassFileTransformer初始化之前加载,因此该类将不会调用Java agent:transform()