当前位置: 首页 > 知识库问答 >
问题:

Javaagent应用程序类未附加到transformer

柴兴贤
2023-03-14

我正在使用javaagent(带有Javaassit)通过

方法和我对ClassFileTransformer不考虑类的原因很好奇

简短说明:

  • 我的项目中有两个类,javaagent(premain)应用于这两个类
  • MyMainClass是具有main方法的类
  • MyLogicReference类不是通过导入引用,在MyMainClass中的...
  • 只对MyMainClass调用ClassFileTransformer转换方法,而不对MyLogicReference
  • 如果调用java.lang.Instrument.Instrumentation GetAllloadedClasss,则可以看到MyLogicReference类已加载
  • ?这是代理的工作方式吗?如果是,我如何让代理也转换第二个(MyLogicReference)类?

更新

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

在java.lang.Instrument.Instrumentation.ReTransformClasss中,我应该能够从示例中注册MyLogicReference类。但我还是很奇怪...让我们试试...

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

详细说明:

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

public class MyMainClass {

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

  @MyAnnotationToApplyLogic
  public void myMethod(){
    //Some code here
  }
@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方法

我可以看到MyLogicReference类。但从不为该类调用ClassFileTransformer。这对javaagents是正确的吗?

例如,如果我在MyMainClass中导入MyLogiReference.class,我就会发现调用了transformer。

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

我的JavaAgent清单项(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

共有1个答案

闾丘晨
2023-03-14

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

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

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

  • 分离javaagent使用的代码和正在检测的代码。
  • 仅将MyLogicReference引用为字符串,例如。使用foo.getClass().getName().equals(“MyLogicReference”)代替fooinstanceof MyLogicReference

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

 类似资料:
  • 问题内容: 我在log4j2中创建了一个自定义附加程序。使用自定义追加程序时,出现以下错误:“ ERROR试图追加到未启动的追加程序”。任何帮助表示赞赏。 问题答案: Log4j 2将检查每个日志事件附加器是否处于可用状态。您看到的错误是Log4j检测到尚未准备好使用附加程序。 一些附加器需要进行准备才能使用。在生命周期的方法是其中追加程序可以做初始化的地方。Log4j不会将事件路由到未处于STA

  • 我的的一个有一个奇怪的问题。我有一个,里面有三个。到现在为止一切正常。当应用程序启动时,(带有)附加了三个片段,这样我就可以毫无问题地从一个浏览到另一个。当我尝试像这样手动(注销后)重新启动应用程序时,问题就来了: 现在,当我注销和应用程序重新启动时,应用程序崩溃,并通过一个试图从片段上访问资源。 下面是我附加的代码,即: 然后,设置:

  • 问题内容: 您可以使用Eclipse附加到正在运行的应用程序,类似于使用Visual Studio附加方式吗? 问题答案: 是。 如果在打开调试端口的情况下启动服务器,请将其添加到java命令中: 并且您的项目中有源代码(从技术上讲这不是必需的,但是除非您这样做,否则它是无用的),您可以通过使用host =服务器所在的机器设置“调试配置”来连接到正在运行的服务器在端口= 8888上运行(例如-参见

  • 我正在使用Java代理和Javassist向一些JDK类添加一些日志记录。实际上,当系统加载一些TLS类时,Javassist会向它们添加一些额外的字节码,以帮助我调试一些连接问题。 问题是,考虑到这个类包含在代理jar中: 在我的代理的转换方法中,假设我试图使用javassist调用该类: 你认为这行得通,但我得到了这个: 有没有办法将该类[]添加到应用程序的类路径中?

  • 我一直在工作一个100%的SwiftUI应用程序,并相当投入该项目。当在模拟器和设备上运行时,该项目编译和构建没有问题。然而,如果我试图编译项目,我会得到一堆错误,说明在整个项目中找不到某些类。 其中2个是CoreData自动生成的类。1是一个名为globals.swift的全局结构 还有谁在Xcode 12.4中遇到过这个问题吗?

  • 我想知道是否可以将spring的其他参数(如)添加到spring boot app中,以便将其作为服务运行。 我检查了由自动生成的脚本: 所以也许它可以通过maven插件的选项来完成,但是除了JVM参数之外找不到其他的,这不是那么有用...