模块  java.instrument
软件包  java.lang.instrument

Interface ClassFileTransformer


  • public interface ClassFileTransformer
    类文件的转换器。 代理使用addTransformer方法注册此接口的实现,以便在加载类时调用转换器的transform方法, redefinedretransformed 该实现应覆盖此处定义的transform方法之一。 在Java虚拟机定义类之前调用变换器。

    有两种变压器,由canRetransform参数Instrumentation.addTransformer(ClassFileTransformer,boolean)决定

    一旦变换器注册了addTransformer ,将为每个新的类定义和每个类重新定义调用变换器。 每个类重新转换也将调用具有重新转换能力的变换器。 使用ClassLoader.defineClass或其本机等效项来请求新的类定义。 类重新定义的请求使用Instrumentation.redefineClasses或其原生等价物。 类重新转换的请求使用Instrumentation.retransformClasses或其本机等效项进行。 在验证或应用类文件字节之前,在处理请求期间调用变换器。 当存在多个变换器时,通过链接transform调用来组成变换。 也就是说,一次调用transform返回的字节数组成为下一次调用的输入(通过classfileBuffer参数)。

    转换按以下顺序应用:

    • 重新变换无能为力的变形金刚
    • 转换无能为力的本地变形金刚
    • 具有转换能力的变压器
    • 具有转换能力的原生变换器

    对于重新转换,不调用无重新转换的变换器,而是重用先前转换的结果。 在所有其他情况下,调用此方法。 在每个分组中,变换器按注册顺序调用。 本机转换器由Java虚拟机工具接口中的ClassFileLoadHook事件提供。

    第一个变压器的输入(通过classfileBuffer参数)是:

    • 对于新的类定义,传递给ClassLoader.defineClass的字节ClassLoader.defineClass
    • 类重定义, definitions.getDefinitionClassFile()其中definitions为参数Instrumentation.redefineClasses
    • 对于类重新转换,传递给新类定义的字节,或者,如果重新定义,则是最后一次重新定义,所有由转换无能力转换器进行的转换都会自动重新应用并且不会改变; 详情请见Instrumentation.retransformClasses

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

    在重新转换和重新定义的情况下,变换器必须支持重新定义语义:如果稍后重新转换或重新定义变换器在初始定义期间更改的类,则变换器必须确保第二类输出类文件是第一个输出的合法重新定义类文件。

    如果变换器抛出异常(它没有捕获),则仍会调用后续变换器,仍然会尝试加载,重新定义或重新转换。 因此,抛出异常与返回null具有相同的效果。 为了防止在变换器代码中生成未经检查的异常时出现意外行为,变换器可以捕获Throwable 如果变压器认为classFileBuffer不代表有效格式的类文件,则应抛出IllegalClassFormatException ; 虽然这与返回null具有相同的效果。 它有助于记录或调试格式损坏。

    请注意,术语类文件的使用方法在The Java™ Virtual Machine Specification的第3.1节中定义 ,表示类文件格式的字节序列,无论它们是否驻留在文件中。

    从以下版本开始:
    1.5
    另请参见:
    Instrumentation
    • 方法详细信息

      • transform

        default byte[] transform​(ClassLoader loader,
                                 String className,
                                 <?> classBeingRedefined,
                                 ProtectionDomain protectionDomain,
                                 byte[] classfileBuffer)
                          throws IllegalClassFormatException
        转换给定的类文件并返回一个新的替换类文件。 如果未覆盖模块轴承transform则调用此方法。
        实现要求:
        默认实现返回null。
        参数
        loader - 要转换的类的定义加载程序,如果引导加载程序可能是 null
        className - Java虚拟机规范中定义的完全限定类和接口名称的内部形式的类的名称。 例如, "java/util/List"
        classBeingRedefined - 如果由重新定义或重新转换触发,则重新定义或重新转换类; 如果这是一个类加载, null
        protectionDomain - 正在定义或重新定义的类的保护域
        classfileBuffer - 类文件格式的输入字节缓冲区 - 不得修改
        结果
        格式良好的类文件缓冲区(转换结果),如果不执行转换, null
        异常
        IllegalClassFormatException - 如果输入不表示格式良好的类文件
      • transform

        default byte[] transform​(模块 module,
                                 ClassLoader loader,
                                 String className,
                                 <?> classBeingRedefined,
                                 ProtectionDomain protectionDomain,
                                 byte[] classfileBuffer)
                          throws IllegalClassFormatException
        转换给定的类文件并返回一个新的替换类文件。
        实现要求:
        此方法的默认实现调用 transform方法。
        参数
        模块 - 要转换的类的模块
        loader - 要转换的类的定义加载程序,如果引导加载程序可能是 null
        className - Java虚拟机规范中定义的完全限定类和接口名称的内部形式的类的名称。 例如, "java/util/List"
        classBeingRedefined - 如果由重新定义或重新转换触发,则重新定义或重新转换类; 如果这是类加载, null
        protectionDomain - 正在定义或重新定义的类的保护域
        classfileBuffer - 类文件格式的输入字节缓冲区 - 不得修改
        结果
        格式良好的类文件缓冲区(转换结果),如果不执行转换, null
        异常
        IllegalClassFormatException - 如果输入不表示格式良好的类文件
        从以下版本开始:
        9