Module  java.instrument
软件包  java.lang.instrument

Interface ClassFileTransformer



  • public interface ClassFileTransformer
    类文件的变压器。 代理使用addTransformer方法注册该接口的实现,以便在加载类redefinedretransformed时调用变压器的transform方法。 实现应该覆盖这里定义的一个transform方法。 在类由Java虚拟机定义之前调用变形金刚。

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

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

    转换按以下顺序应用:

    • 转换无变压器
    • 重新转换无能力的原生变压器
    • 可转换变压器
    • 可转换能力的天生变压器

    对于重新形成,不调用不可转换的变换器,而是重新使用先前转换的结果。 在所有其他情况下,调用此方法。 在这些分组中的每一个中,变压器按照登记的顺序进行调用。 本机变压器由Java虚拟机工具接口中的ClassFileLoadHook事件提供)。

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

    • 对于新的类定义,字节传递给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,
                                 Class<?> classBeingRedefined,
                                 ProtectionDomain protectionDomain,
                                 byte[] classfileBuffer)
                          throws IllegalClassFormatException
        转换给定的类文件并返回一个新的替换类文件。 Module轴承transform不被覆盖时,将调用此方法。
        实现要求:
        默认实现返回null。
        参数
        loader - 要转换的类的定义加载器,可以是 null如果引导加载程序
        className - Java虚拟机规范中定义的完全限定类和接口名称的内部形式的类的名称。 例如, "java/util/List"
        classBeingRedefined - 如果这是由重新定义或重新转换触发的,则重新定义或重新转换该类; 如果这是一个类加载, null
        protectionDomain - 定义或重新定义类的保护域
        classfileBuffer - 类文件格式的输入字节缓冲区 - 不能修改
        结果
        一个格式良好的类文件缓冲区(转换结果),如果没有进行转换, null
        异常
        IllegalClassFormatException - 如果输入不表示一个格式良好的类文件
      • transform

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