我有一个非常简单的变压器:
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()?
谢谢
答案 0 :(得分:0)
在附加代理时,您只看到尚未加载的类。如果要处理已加载的类,则必须显式重新转换这些类。你可以这样做:
instrumentation.retransformClasses(instrumentation.getLoadedClasses());
但是,某些类不可重新转换(Instrumentation::isModifiable
),您很可能需要拆分数组以避免耗尽内存。
答案 1 :(得分:0)
可能有两种情况,
类尚未由JVM加载
如果JVM尚未加载任何类,则有可能不会为该类调用Java agent:transform()。
每当由JVM Java代理加载时,都会为该类调用transform()。
在初始化ClassFileTransformer之前加载类
如果您在ClassFileTransformer实现中使用了任何类或任何其他Agent类,则该类可能在ClassFileTransformer初始化之前加载,因此该类将不会调用Java agent:transform()