RedirectorTransformer 与 ClassHeirachyManager

基本信息

属性 值
转换器 1 codechicken.lib.asm.RedirectorTransformer
转换器 2 codechicken.lib.asm.ClassHeirachyManager
注册位置 CodeChickenCorePlugin.java:63 getASMTransformerClass(),无条件返回
实现接口 均实现 net.minecraft.launchwrapper.IClassTransformer

两者是本模组仅有的两个无条件注册的 ASM 转换器(getASMTransformerClass() 固定返回这 2 个字符串),与 TweakTransformer、DelegatedTransformer 的条件注册形成对比。

RedirectorTransformer

作用

它做的是一次字节码级 API 兼容:把老版本 CodeChickenLib 中对 CCRenderState 静态字段/静态方法的访问,改写成对 ThreadLocal 实例的访问。

CCRenderState 现在持有 private static final ThreadLocal<CCRenderState> instances = ThreadLocal.withInitial(CCRenderState::new) 与 public static CCRenderState instance()(CCRenderState.java:32、:38-40),并带注释 Backported from CCL - 1.16.x(:25)——即这套实例化设计是从 CCL 1.16 分支回移植到 1.7.10 的。老 mod 编译产物里的 GETSTATIC 一旦对不上现在的实例字段,类加载就会失败,转换器的作用正是在此拦一道。

触发条件

transform()(RedirectorTransformer.java:91-94)先用常量池解析器判断字节码里是否出现过 codechicken/lib/render/CCRenderState 这个 owner(RenderStateClass 常量在 :35),没出现就原样返回。ClassConstantPoolParser 在静态块中以该类名构造(:89)。

重定向目标

三个目标集合在静态块中用 Collections.addAll 填充(RedirectorTransformer.java:44-88),计数经脚本解析核实:

集合 数量 行 变换方式
redirectedFields 25 :44-70 GETSTATIC → 插入 INVOKESTATIC instance() 后改 GETFIELD;PUTSTATIC → 插入 instance() + SWAP 后改 PUTFIELD(:106-127)
redirectedSimpleMethods 5 :72 INVOKESTATIC name(...) → 插入 instance() 后改 INVOKEVIRTUAL name**Instance**(...)(:129-138)
redirectedMethods 11 :73-86 已是 INVOKEVIRTUAL 的调用保持不变(:139-141 注释:处理已迁移到新 API 的 mod)

25 个字段名:pipeline、model、firstVertexIndex、lastVertexIndex、vertexIndex、baseColour、alphaOverride、useNormals、computeLighting、useColour、lightMatrix、vert、hasNormal、normal、hasColour、colour、hasBrightness、brightness、side、lc、normalAttrib、colourAttrib、lightCoordAttrib、sideAttrib、lightingAttrib。

5 个简单方法名:reset、pullLightmap、pushLightmap、setDynamic、draw。

11 个方法名:setPipeline、bindModel、setModel、setVertexRange、render、runPipeline、writeVert、setNormal、setColour、setBrightness、startDrawing。

关键实现事实

对 redirectedSimpleMethods,方法名被追加后缀 Instance(:135 mNode.name = mNode.name + "Instance")。已逐个核实这 5 个目标在 CCRenderState 中确实存在:resetInstance、pullLightmapInstance、pushLightmapInstance、setDynamicInstance、drawInstance 各命中 1 处。

而 25 个 redirectedFields 目标在当前 CCRenderState 中已无一是静态字段。对 CCRenderState.java 全文件枚举静态字段声明,只剩两处且都不在重定向列表内:

行 声明 是否在重定向列表
:32 private static final ThreadLocal<CCRenderState> instances 否
:42 private static volatile int nextOperationIndex 否

也就是说,字段分支是一层纯粹的历史兼容层,服务于仍持有旧版静态字段字节码的第三方 mod;方法分支则仍在服务当前 API 生态。

调试开关

DUMP_CLASSES 由系统属性 -Dccl.dumpClass 控制(:34),配合 Textifier / TraceClassVisitor 输出反编译文本。

ClassHeirachyManager

codechicken.lib.asm.ClassHeirachyManager(拼写为 Heirachy,非 Hierarchy)是第二个无条件转换器。它的类注释写明用途:“This is added as a class transformer if CodeChickenCore is installed. Adding it as a class transformer will speed evaluation up slightly by automatically caching superclasses when they are first loaded.”(ClassHeirachyManager.java:14-16)

机制:transform()(:27-33)对每个未见过的类名调用 declareASM(),用 ClassReader 读出继承信息存进 ConcurrentHashMap<String, ClassInfo>(:20)。declareReflection()(:41-45)提供反射路径作为补充。

它在本仓内的唯一消费者是 codechicken.lib.asm.CC_ClassWriter:

调用 行
ClassHeirachyManager.classExtends(d, c) CC_ClassWriter.java:22
ClassHeirachyManager.classExtends(c, d) CC_ClassWriter.java:23
ClassHeirachyManager.getSuperClass(c, runtime) CC_ClassWriter.java:25
ClassHeirachyManager.classExtends(d, c) CC_ClassWriter.java:26

即:写回字节码时需要判断两个类型是否继承相关,缓存避免每次重走反射。CC_ClassWriter 是 ASM 工具包 的一部分。

相关条目