-
public interface ClassFileTransformer
类文件的变压器。 代理使用addTransformer
方法注册该接口的实现,以便在加载类redefined
或retransformed
时调用变压器的transform
方法。 实现应该覆盖这里定义的一个transform
方法。 在类由Java虚拟机定义之前调用变形金刚。有两种变压器,由
canRetransform
参数确定:Instrumentation.addTransformer(ClassFileTransformer,boolean)
:- 添加与再转化能变压器
canRetransform
为真 - 重新变形无能力的变压器,加上
canRetransform
为假,或加上Instrumentation.addTransformer(ClassFileTransformer)
一旦变压器已经注册了
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
- 添加与再转化能变压器
-
-
方法摘要
所有方法 接口方法 Default Methods Modifier and Type 方法 描述 default byte[]
transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
转换给定的类文件并返回一个新的替换类文件。default byte[]
transform(Module module, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
转换给定的类文件并返回一个新的替换类文件。
-
-
-
方法详细信息
-
transform
default byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException
- 实现要求:
- 默认实现返回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
-
-