retransformClasses:查看版本 v1
由 朝武芳乃 于 2026-10-04 02:03 保存 · 2055 字节
''本条基于 Java 17(Minecraft 1.20.1 所用版本),HotSpot 行为以 JDK 17 为准。''
'''retransformClasses'''(<code>Instrumentation.retransformClasses(Class...)</code>)让已加载的类重新走一遍 transformer 链:从“基线字节码”出发,由 transformer 重新生成类定义并安装。底层对应 [[JVMTI]] 的 <code>RetransformClasses</code>。
== 用法 ==
* agent 清单声明 <code>Can-Retransform-Classes: true</code>,可用 <code>isRetransformClassesSupported()</code> 检查。
* transformer 必须用 <code>addTransformer(transformer, true)</code> 注册为“可重转换”才会参与重转换。
* 先用 <code>isModifiableClass</code> 过滤掉不可修改的类。
== 基线 ==
retransform 的输入不是类当前的字节码,而是类的'''基线''':
* 类被 defineClass 定义时传入的原始字节(transformer 处理之前);
* 如果之后调用过 [[redefineClasses]],基线就变成最近一次 redefine 传入的字节。
所以基线会被 defineClass 或 redefine 改变,而 retransform 本身不改变基线。
* 一般只有定义类时已有可重转换的 agent,JVM 才会缓存原始字节;否则需要时由已加载的类结构还原出基线,可能与原始字节不完全一致。
* [[TransformingClassLoader]] 在 defineClass 之前就改好了字节码,所以 [[Mixin]] 的结果已经包含在基线里,retransform 不会把它去掉。
== 处理顺序 ==
基线 → 此前经过的“不可重转换”transformer 的输出(直接沿用,不重新执行)→ 各“可重转换”transformer 依次重新处理 → 安装结果。
== 特点 ==
* '''可撤销''':每次都从基线出发,移除 transformer 后再 retransform 就能回到基线。
* transformer 应当对同一份输入每次产生同样的结果,不要依赖“类已经被改过”。
* 限制与 [[redefineClasses]] 相同:只能改方法体,不能增删成员;[[隐藏类]]不可修改。
参见:[[redefineClasses]]、[[Instrumentation]]、[[InstrumentationImpl]]
其他版本
- v1 · 2026-10-04 02:03 · 朝武芳乃 · 新建条目