繁体   English   中英

字节码操作/增强和 Java Instrumentation API

[英]Bytecode manipulation/enhancement and Java Instrumentation API

我很难理解字节码操作/增强和 Java Instrumentation API 之间的依赖关系。

根据我对执行任何字节码操作/增强的理解,我们有两种选择

  • 构建时 - Java 类被编译为*.class然后应该执行一些其他库/应用程序来进行操作。
  • 加载时间 - 仅通过使用 Java Instrumentation API,这意味着必须提供特定的 javaagent。

我不确定的事情:

  • 是否有诸如构建时字节码操作之类的东西,哪些框架/库支持该操作(例如 Javassist、ASM),它们是使用一些通用方法还是仅读取和解析字节码,然后为您提供修改它的方法?

  • 加载时操作是否仅依赖于 Java Instrumentation API? 意思是所有可用的框架/库(例如 Javassist、ASM)都使用 javaagent 来进行操作?

请注意,我对这个主题的经验非常少,所以我有可能误解或遗漏了一些概念。 我试图将这个复杂的主题归结为一些简单的解释,即使它非常笼统或使用类比来演示。

将编译后的 Java 类文件视为包含特定 Java 类的任何信息的byte[]数组。 在此上下文中,检测是指将此字节数组后处理为不同形状的过程,与何时或如何发生无关。 可以在编译和类加载之间的任何时间应用检测; 在 Java 中,一个类甚至可以在加载后进行检测,但不能改变其形状,即添加/删除字段或方法。 但是无论何时应用检测,概念都保持不变,即重新排列表示已编译 Java 类的字节数组。

我知道的任何字节码操作库都允许处理来自任何来源的类文件。 通常,这些库的最通用输入是一个简单的字节数组,为了方便,可以选择从类加载器加载它。 可以通过ClassLoader.getResourceAsStream方法从类加载器中查找类文件,并将类文件的名称作为参数。 例如:

classLoader.getResourceAsStream("some/Sample.class")

应该为虚构的some.Sample类解析类文件。 这通常是因为类文件(字节数组)需要由类加载器定位以在第一次请求时加载类。

在构建时,类文件通常位于特定文件夹中,例如在 Maven 构建的target/classes文件夹中。 要检测这些类,您只需找到这些文件,将它们读入字节数组,然后写回更改后的结果。 例如,您可以通过编写自己的 Maven 插件来做到这一点,例如,您可以在其中使用 ASM 来调整文件。 为方便起见,您也可以使用更高级的库,例如Byte Buddy 的 Maven 插件,您可以在其中加载自己的插件,并完全避免 Maven 插件 API 甚至字节码 API。 (有关信息,我是 Byte Buddy 的作者。)

在运行时,您可以执行非常相似的操作,即定位位于某个文件夹或jar文件中的类文件,找到这些类并在应用程序加载它们之前对其进行调整。 然而,这并不总是有效,因为 jar 文件也可能被其他也会受到影响的应用程序使用。 此外,它会要求您的用户从他们的应用程序中明确激活此检测。 因此,类文件的仪器使用Java代理是什么赋予了访问常用于Instrumentation API是什么使这个方便多了。 API 允许在 Java 的内部类加载机制中安装一个钩子,这使得可以在加载之前调整类的字节数组:

instrumentation.addClassFileTransformer(
  (Module module, ClassLoader loader, String name, 
   Class<?> classIfLoaded, ProtectionDomain pd, byte[] classFile) -> {
     byte[] transformed = doSomethingWith(classFile);
     return transformed;
});

此更改随后与应用程序隔离,并且不会更改原始类文件。 检测 API 并不意味着使用任何库来修改类文件,这完全取决于您,每个人都在使用某种库,甚至直接操作字节数组。 像 Byte Buddy 这样的高级库甚至不需要您实现自己的类文件转换器,而是通过AgentBuilder API 拥有自己的抽象,但它会在AgentBuilder创建类文件转换器以利用检测 API 的独特功能. 但是,其他库(例如 ASM 或 Javassist)与Instrumentation API 没有关系,并且需要您实现自己的类文件转换器,在其中使用这些库的 API 来处理呈现的类文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM