redefineClasses:查看版本 v1
由 朝武芳乃 于 2026-10-04 02:03 保存 · 1873 字节
''本条基于 Java 17(Minecraft 1.20.1 所用版本),HotSpot 行为以 JDK 17 为准。''
'''redefineClasses'''(<code>Instrumentation.redefineClasses(ClassDefinition...)</code>)直接用调用者给出的字节码替换已加载类的定义,不参考类原有的字节码。底层对应 [[JVMTI]] 的 <code>RedefineClasses</code>,也就是调试器“热替换”用的机制。
== 用法 ==
* agent 清单声明 <code>Can-Redefine-Classes: true</code>,可用 <code>isRedefineClassesSupported()</code> 检查。
* 参数是 <code>ClassDefinition(Class, byte[])</code>,可一次传多个类,要么全部成功,要么全部失败。
* 传入的字节码同样会经过已注册的 transformer(见 [[Instrumentation]])。
== 限制 ==
* 只能改方法体、常量池等,不能增删或改名字段与方法,不能改访问修饰符、父类和接口(HotSpot 默认不支持,会抛 <code>UnsupportedOperationException</code>)。
* 类名必须一致,字节码要通过校验。
* 不会重新执行静态初始化器,已有实例的字段值不变;正在执行的旧方法栈帧继续跑旧代码,新调用才使用新代码。
* 基本类型、数组类和[[隐藏类]]不可修改,<code>isModifiableClass</code> 返回 false。
== 与 retransformClasses 的区别 ==
* '''起点不同''':redefine 完全以传入的字节为准;[[retransformClasses]] 从“基线”字节出发,再让 transformer 重新处理。
* '''会改变基线''':redefine 成功后,类的基线被换成这次传入的字节,之后的 retransform 以它为起点。
* '''不可撤销''':redefine 之后原来的字节码不会自动保留,要还原只能自己保存原字节再 redefine 一次;retransform 则可以靠移除 transformer 后重新 retransform 回到基线。
参见:[[retransformClasses]]、[[JavaAgent]]、[[Mixin]]
其他版本
- v1 · 2026-10-04 02:03 · 朝武芳乃 · 新建条目