我正在通过
使用javaagent(使用Javaassit)premain(String agentArgs,Instrumentation inst)
方法,我很好奇为什么ClassFileTransformer不考虑类
简短说明:
更新
我想我在Javadocs https://docs.oracle.com/javase/7/docs/api/java/lang/instrument/ClassFileTransformer.html中找到了一些有用的信息。
在java.lang.instrument.Instrumentation.retransformClasses中,我应该可以从示例中注册MyLogicReference类。但我仍然对这种行为感到疑惑......让我们尝试一下......
对于添加了canRetransform true的每个变换器,在这些变换器中调用transform方法
详细说明:
我正在使用代理来改变方法,...通过注释(某种注入)。
我已经将类拆除为下面的onces,我想知道为什么只有MyMainClass被放到javaagent转换器(classfilebuffer)而不是MyLogicReference类。
public class MyMainClass {
... //Main method and call of myMethod();
@MyAnnotationToApplyLogic
public void myMethod(){
//Some code here
}
我的流程更改代码的入口点是我引用另一个类(MyLogicReference)的注释......
@Documented
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.CLASS)
@Functional(value = MyLogicReference.class, type = ElementType.PARAMETER)
public @interface MyAnnotationToApplyLogic {
}
public class MyLogicReference {
// @MyAnnotationToApplyLogic in the MyMainClass method references to this class
// The Javaagent Class file transformer adjust the MyMainClass.myMethod code based on the annotation
public void mySecondMethod(){
}
}
如果我使用
java.lang.instrument.Instrumentation getAllLoadedClasses method
我可以看到MyLogicReference类。但是从未为此类调用ClassFileTransformer。这对javaagents是否正确?
如果我,例如在MyMainClass中导入MyLogiReference.class,我发现调用了变换器。
所以我目前的假设是只有类/子类 直接引用主类被发送到 ClassFileTransformer 即可。如果这是正确的,我怎么强迫 javaagent转换一个之前没有被转换过的类?
我的javaaagent清单条目(MVN):
<Premain-Class>com.MyTestAgent</Premain-Class>
<Agent-Class>com.MyTestAgent</Agent-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
我将ClassFileTransformer剥离到了这个,第二个类仍未加载:
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
if (!className.startsWith("java/") && !className.startsWith("javax/") && !className.startsWith("sun/")) {
log("NOW PROCESSING: " + className);
return classfileBuffer;
}
return null;
}
//Output:
//NOW PROCESSING: MyMainClass
答案 0 :(得分:0)
根据您的说法,我猜您在javaagent代码的某个地方指的是 MyLogicReference 。因此,JVM在检测开始之前加载类。要记住两件事:
使用 java.lang.instrument.Instrumentation #revertformClasses 在这里似乎也没有必要。在我看来,最好避免它(为了简单起见)。你可以:
foo.getClass().getName().equals("MyLogicReference")
代替foo instanceof MyLogicReference
根据提供的信息,我还想知道您是否考虑使用注释处理器(https://docs.oracle.com/javase/7/docs/api/javax/annotation/processing/Processor.html)。