java.lang.instrument

接口
异常
public interface ClassFileTransformer

一个提供此接口的实现以转换类文件的代理。转换在 JVM 定义类之前发生。

注意,根据 The Java Virtual Machine SpecificationThe class File Format 一章中的定义使用术语类文件,它指以类文件格式表示的字节序列,无论这些字符是否驻留在文件中。

从以下版本开始:
1.5
另请参见:
Instrumentation, Instrumentation.addTransformer(java.lang.instrument.ClassFileTransformer, boolean), Instrumentation.removeTransformer(java.lang.instrument.ClassFileTransformer)

方法摘要
 byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
          此方法的实现可以转换提供的类文件,并返回一个新的替换类文件。
 

方法详细信息

transform

byte[] transform(ClassLoader loader,
                 String className,
                 Class<?> classBeingRedefined,
                 ProtectionDomain protectionDomain,
                 byte[] classfileBuffer)
                 throws IllegalClassFormatException
此方法的实现可以转换提供的类文件,并返回一个新的替换类文件。

有两种装换器,由 Instrumentation.addTransformer(ClassFileTransformer,boolean)canRetransform 参数确定:

在转换器使用 addTransformer 注册之后,每次定义新类和重定义类时都将调用该转换器。每次重转换类时还将调用可重转换转换器。对新类定义的请求通过 ClassLoader.defineClass 或其本机等价方法进行。对类重定义的请求通过 Instrumentation.redefineClasses 或其本机等价方法进行。对类重转换的请求将通过 Instrumentation.retransformClasses 或其本机等价方法进行。转换器是在验证或应用类文件字节之前的请求处理过程中调用的。 当存在多个转换器时,转换将由 transform 调用链组成。 也就是说,一个 transform 调用返回的 byte 数组将成为下一个调用的输入(通过 classfileBuffer 参数)。

转换将按以下顺序应用:

  • 不可重转换转换器
  • 不可重转换本机转换器
  • 可重转换转换器
  • 可重转换本机转换器

对于重转换,不会调用不可重转换转换器,而是重用前一个转换的结果。对于所有其他情况,调用此方法。在每个这种调用组中,转换器将按照注册的顺序调用。本机转换器由 Java 虚拟机 Tool 接口中的 ClassFileLoadHook 事件提供。

第一个转换器的输入(通过 classfileBuffer 参数)如下:

  • 对于新的类定义,是传递给 ClassLoader.defineClass 的 byte
  • 对于类重定义,是 definitions.getDefinitionClassFile(),其中 definitionsInstrumentation.redefineClasses 的参数
  • 对于类重转换,是传递给新类定义的 byte,或者是最后一个重定义(如果有重定义),所有不可转换转换器进行的转换都将自动重新应用并保持不变;有关细节,请参阅 Instrumentation.retransformClasses

如果实现方法确定不需要进行转换,则应返回 null。否则,它将创建一个新的 byte[] 数组,将输入 classfileBuffer 连同所有需要的转换复制到其中,并返回这个新数组。不得修改输入 classfileBuffer

在重转换和重定义中,转换器必须支持重定义语义:如果转换器在初始定义期间更改的类在以后要重转换或重定义,那么转换器必须确保第二个输出类文件是第一个输出类文件的合法重定义文件。

如果转换器抛出异常(未捕获的异常),后续转换器仍然将被调用并加载,仍然将尝试重定义或重转换。因此,抛出异常与返回 null 的效果相同。若要使用转换器代码在生成未检验异常时防止不希望发生的行为,可以让转换器捕获 Throwable。 如果转换器认为 classFileBuffer 不表示一个有效格式的类文件,则将抛出 IllegalClassFormatException;尽管这与返回 null 的效果相同,但它便于对格式毁坏进行记录或调试。

参数:
loader - 定义要转换的类加载器;如果是引导加载器,则为 null
className - 完全限定类内部形式的类名称和 The Java Virtual Machine Specification 中定义的接口名称。例如, "java/util/List"
classBeingRedefined - 如果是被重定义或重转换触发,则为重定义或重转换的类;如果是类加载,则为 null
protectionDomain - 要定义或重定义的类的保护域
classfileBuffer - 类文件格式的输入字节缓冲区(不得修改)
返回:
一个格式良好的类文件缓冲区(转换的结果),如果未执行转换,则返回 null
抛出:
IllegalClassFormatException - 如果输入不表示一个格式良好的类文件
另请参见:
Instrumentation.redefineClasses(java.lang.instrument.ClassDefinition...)