0 instrumentation bytecode agent java-bytecode-asm
是否可以在没有 Java 代理的情况下动态检测 Java 字节码?我之前使用 Java 代理检测过字节码,做了类似的事情:
ClassFileTransformer myTransformer = new Transformer();
instrument.addTransformer(myTransformer, true);
instrument.retransformClasses(classInstance);
instrument.removeTransformer(myTransformer);
Run Code Online (Sandbox Code Playgroud)
但是,如果不使用 Java 代理,这可能吗?我想要做的是调用一个方法,该方法将在 JVM 运行后的任何给定时间进行检测,而无需使用代理。
在没有实现实例的情况下执行字节码转换的唯一方法Instrumentation是
自定义类加载器,可以在调用之前更改字节defineClass(仅限于通过该加载器加载的类)
MethodHandles.Lookup.defineClass甚至在类加载之前就使用修改后的字节进行调用,这适用于具有延迟加载的广泛 JVM,但仅限于您自己的模块或向您的模块打开的模块
这两种方法都不能更改已加载的类。这需要Instrumentation引用,而 JVM 分发此类引用的唯一地方是 Java 代理的初始化方法。因此,要使用它,Java 代理是不可避免的,即使它可能只是存储引用的存根,供应用程序代码使用。
请注意,从 Java\xc2\xa09 开始,Launcher-Agent-Classjar 文件有一个 Manifest 属性,可以指定在启动指定的类之前启动的 Java Agent 的类Main-Class。这样,您就可以轻松地让代理与 JVM 中的应用程序代码进行协作,而无需任何其他命令行选项。代理可以像agentmain在主类中使用一个方法一样简单,将Instrumentation引用存储在静态变量中。
请参阅包文档\java.lang.instrument xe2\x80\xa6
Instrumentation当 JVM 尚未通过代理启动时,获取实例会比较棘手。一般来说,它必须支持在启动后启动代理,例如通过 Attach API。这个答案在最后展示了这样一个自我附加来获得Instrumentation. 当您的应用程序 jar 文件中有必要的清单属性时,您甚至可以将其用作代理 jar 并省略临时存根文件的创建。
然而,最近的 JVM 禁止自附加,除非-Djdk.attach.allowAttachSelf=true在启动时指定,但我想,在启动时采取额外的步骤,正是您不想做的\xe2\x80\x99 想做的事情。避免这种情况的一种方法是使用另一个过程。这个过程所要做的就是附加到您的原始进程并告诉 JVM 启动代理。然后,它可能已经终止,并且其他一切都与引入此限制之前的方式相同。
正如此评论中提到的,Byte-Buddy 已经实现了这些必要的步骤,并且精简的 Byte-Buddy-Agent 仅包含该逻辑,因此您可以使用它来构建您自己的逻辑。
\n| 归档时间: |
|
| 查看次数: |
1244 次 |
| 最近记录: |