Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javaagent应用程序类未连接到transformer_Java_Javassist_Javaagents - Fatal编程技术网

Javaagent应用程序类未连接到transformer

Javaagent应用程序类未连接到transformer,java,javassist,javaagents,Java,Javassist,Javaagents,我正在通过 premain(管柱代理、仪器仪表) 方法,我很好奇为什么ClassFileTransformer不考虑类 简短描述: 在我的项目中,有两个类应用了javaagent(premain) MyMainClass是具有main方法的类 MyLogicReference类不是通过导入的引用。。。在我的课堂上 ClassFileTransformer转换方法仅为MyMainClass调用,而不为MyLogiCreefence调用 如果我调用java.lang.instrument.Inst

我正在通过

premain(管柱代理、仪器仪表)

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

简短描述:

  • 在我的项目中,有两个类应用了javaagent(premain)
  • MyMainClass是具有main方法的类
  • MyLogicReference类不是通过导入的引用。。。在我的课堂上
  • ClassFileTransformer转换方法仅为MyMainClass调用,而不为MyLogiCreefence调用
  • 如果我调用java.lang.instrument.Instrumentation GetAllLoadedClass,那么我可以看到MyLogicReference类已加载
  • ?这是代理的工作方式吗?如果是,如何让代理同时转换第二个(MyLogiCreefence)类?
更新

我想我在Javadocs中找到了一些有用的信息

在java.lang.instrument.Instrumentation.retransformClasses中,我应该能够从示例中注册MyLogicReference类。但我还是想知道他们的行为。。。让我们试试看

对于添加了canRetransform true的每个转换器 在这些转换器中调用transform方法

详细说明:

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

我已经将这些类剥离到下面的once,我想知道为什么只有MyMainClass放在javaagent transformer(classfilebuffer)中,而没有放在MyLogicReference类中

public class MyMainClass {

  ... //Main method and call of myMethod();      

  @MyAnnotationToApplyLogic
  public void myMethod(){
    //Some code here
  }
我更改代码的过程的入口点是我引用另一个类(MyLogicReference)的注释

如果我使用

java.lang.instrument.Instrumentation getAllLoadedClasses方法

我可以看到MyLogicReference类。但是这个类永远不会调用ClassFileTransformer。这对JavaAgent正确吗

例如,如果我在MyMain类中导入MyLogiReference.class,我就知道调用了transformer

所以我目前的假设是,只有 在主类上直接引用的将被发送到 ClassFileTransformer。如果这是正确的,我如何强制 javaagent转换一个以前没有转换过的类

我的javaaagent清单条目(MVN):

com.MyTestAgent
com.MyTestAgent
真的
真的
我将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
@覆盖
公共字节[]转换(类加载器加载器、字符串类名、类正在重新定义、ProtectionDomain ProtectionDomain、字节[]类文件缓冲区)引发IllegalClassFormatException{
如果(!className.startsWith(“java/”)&&!className.startsWith(“javax/”&&!className.startsWith(“sun/”)){
日志(“正在处理:“+className”);
返回类文件缓冲区;
}
返回null;
}
//输出:
//现在正在处理:MyMainClass

根据您所说的,我猜您指的是javaagent代码中的某个地方。因此,JVM在检测开始之前加载该类。要记住两件事:

  • Java代理只是一个Java程序,它需要加载类
  • Java代理在加载时转换类。对于在java代理启动之前加载的任何类,您都需要使用java.lang.instrument.Instrumentation#retransformClasses(正如您自己所注意到的)
  • 这里似乎也没有必要使用java.lang.instrument.Instrumentation#RetransformClass。在我看来,最好是避免(为了简单起见)。您可以:

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

    根据提供的信息,我还想知道您是否考虑改用Annotation Processor()。

    谢谢您的回答。我已经看过注释处理器(没有详细介绍)。当涉及到修改代码和不构建代理类时,我更喜欢anno之前的代理。有黑客的处理器(如loombok)。此外,代理的速度也适用于我的用例(例如远程JMX…)。另一方面,对于注释驱动的操作,procesor很好(带有编译消息,…)。作为这些主题的新手,对于我来说,使用转换方法的注释处理器将是非常棒的:D
    <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>
    
    @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