gpt4 book ai didi

Javaagent 应用程序类未附加到变压器

转载 作者:行者123 更新时间:2023-12-02 08:51:27 24 4
gpt4 key购买 nike

我通过

使用 javaagent(带有 Javaassit)

premain(String agentArgs, Instrumentation inst)

方法,我很好奇为什么 ClassFileTransformer 不考虑类

简短描述:

  • 我的项目中有两个类,其中应用了 javaagent (premain)
  • MyMainClass 是具有 main 方法的类
  • MyLogicReference 类不是通过导入引用的,...在 MyMainClass
  • 仅为 MyMainClass 调用 ClassFileTransformer 转换方法,但不为 MyLogicReference 调用
  • 如果我调用 java.lang.instrument.Instrumentation getAllLoadedClasses 那么我可以看到 MyLogicReference 类已加载
  • <强>?这是代理的工作方式吗?如果是,我该如何让代理也转换第二个(MyLogicReference)类?

更新

我想我在 Javadocs https://docs.oracle.com/javase/7/docs/api/java/lang/instrument/ClassFileTransformer.html 中找到了一些有用的信息.

在 java.lang.instrument.Instrumentation.retransformClasses 中,我应该能够从示例中注册 MyLogicReference 类。但我仍然想知道这种行为...让我们尝试一下...

for each transformer that was added with canRetransform true, the transform method is called in these transformers

详细:

我正在使用代理来更改方法,...通过注释(某种注入(inject))。

我已将类精简为下面的一次,我想知道为什么只有 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,我就会发现调用了变压器。

So my current assumption is that only classes/subclasses which are directly referenced over the main class are send to the ClassFileTransformer. If this is correct than how can I force the javaagent to transform a class which hasn't been transformed before ?

我的 javaaagent list 条目 (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

最佳答案

根据您所说的,我猜测您是指 javaagent 代码中的MyLogicReference。因此,JVM 在检测启动之前加载该类。需要记住两件事:

  1. Java代理只是一个java程序,它需要加载类。
  2. Java 代理在加载类时对其进行转换。对于在 java 代理启动之前加载的任何类,您将需要使用 java.lang.instrument.Instrumentation#retransformClasses (正如您自己注意到的那样)。

使用java.lang.instrument.Instrumentation#retransformClasses在这里似乎也没有必要。在我看来,最好避免它(为了简单起见)。您可以:

  • 将 javaagent 使用的代码与正在检测的代码分开。
  • 仅将 MyLogicReference 作为字符串引用,例如。使用 foo.getClass().getName().equals("MyLogicReference") 而不是 foo instanceof MyLogicReference

根据提供的信息,我还想知道您是否考虑使用注释处理器( https://docs.oracle.com/javase/7/docs/api/javax/annotation/processing/Processor.html )。

关于Javaagent 应用程序类未附加到变压器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37308217/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com