V2ConstructionReplacerTransformer
基本信息
| 属性 | 值 |
|---|---|
| 类 | com.mitchej123.jarjar.rfb.transformer.V2ConstructionReplacerTransformer |
| Transformer ID | jarjar-v2-construction-replacer |
| RFB 排序 | sortBefore = ["*"] |
| 目标类(4 个) | cpw.mods.fml.common.Loader, cpw.mods.fml.common.ModContainerFactory, cpw.mods.fml.common.discovery.ModDiscoverer, cpw.mods.fml.common.discovery.asm.ASMModParser |
FMLTransformer 只能改 INVOKESTATIC 调用;构造表达式 new Loader() / new ModContainerFactory() / new ModDiscoverer() / new ASMModParser(InputStream) 的重写由 V2ConstructionReplacerTransformer 完成。
改写规则
每个目标类有专属的 methodName/desc/originalClass/newClass:
| 目标类 | 方法 | 改写 |
|---|---|---|
Loader |
instance ()Lcpw/mods/fml/common/Loader; |
NEW cpw/mods/fml/common/Loader → NEW com/mitchej123/jarjar/fml/common/LoaderV2 |
ModContainerFactory |
<clinit> ()V |
NEW cpw/mods/fml/common/ModContainerFactory → NEW com/mitchej123/jarjar/fml/common/ModContainerFactoryV2 |
ModDiscoverer |
<init> ()V |
NEW cpw/mods/fml/common/discovery/ASMDataTable → NEW com/mitchej123/jarjar/fml/common/discovery/ASMDataTableV2 |
ASMModParser |
<init> (Ljava/io/InputStream;)V |
NEW cpw/mods/fml/common/discovery/asm/ModClassVisitor → NEW com/mitchej123/jarjar/fml/common/discovery/asm/ModClassVisitorV2(同时 INVOKESPECIAL owner 改写) |
通用方法
private void transformClass(ClassNode cn, String methodName, String desc,
String originalClass, String newClass, String newClassDesc, String newNewClassDesc) {
for (MethodNode mn : cn.methods) {
if (!(mn.name.equals(methodName) && mn.desc.equals(desc))) continue;
for (int i = 0; i < mn.instructions.size(); i++) {
AbstractInsnNode aInsn = mn.instructions.get(i);
if (aInsn.getOpcode() == Opcodes.NEW && aInsn instanceof TypeInsnNode tInsn) {
if (tInsn.desc.equals(originalClass)) tInsn.desc = newClass;
} else if (aInsn.getOpcode() == Opcodes.INVOKESPECIAL && aInsn instanceof MethodInsnNode mInsn) {
if (mInsn.owner.equals(originalClass) && mInsn.name.equals("<init>") && mInsn.desc.equals(newClassDesc)) {
mInsn.owner = newClass;
}
}
}
}
}
对每个目标方法体里:
NEW <originalClass>→ 描述符改为<newClass>INVOKESPECIAL <originalClass>.<init>(<newClassDesc>)→ owner 改为<newClass>
newNewClassDesc 用于 ASMModParser 的特殊情况:原 ModClassVisitor 构造接受 (Lcpw/mods/fml/common/discovery/asm/ASMModParser;)V,新 ModClassVisitorV2 改为 (Lcom/mitchej123/jarjar/fml/common/discovery/asm/ASMModParserV2;)V。transformer 不改 desc —— 描述符变化由 ASMModParserV2 重写 ASMModParser(InputStream) 构造函数实现(在那里 new ModClassVisitor(this) 自动通过 type 推断指向 ModClassVisitorV2)。
shouldTransformClass
return className.equals(LOADER_CLASSNAME) || className.equals(MOD_CONTAINER_FACTORY_CLASSNAME)
|| className.equals(MOD_DISCOVERER_CLASSNAME) || className.equals(ASM_MOD_PARSER_CLASSNAME);
精确匹配 4 个 FML 顶层类,避免对其它类扫描。
与 FMLTransformer 的分工
| Transformer | 操作 | 涉及位置 |
|---|---|---|
| FMLTransformer | 静态方法调用 (INVOKESTATIC) | 方法体内任意位置 |
| V2ConstructionReplacerTransformer | 对象构造 (NEW + INVOKESPECIAL) | 类初始化 / 单例获取 |
两者组合后,调用方既有的 Loader.instance() → LoaderV2.instance(),又有的 MetadataCollection.from(...) → MetadataCollectionV2.from(...)。
相关条目
- RFB 插件入口 - 注册该 transformer
- FMLTransformer - 静态调用重定向伙伴
- LoaderV2 -
Loader.instance重定向目标 - ModContainerFactoryV2 - clinit 重定向目标
- ASMDataTableV2 - ModDiscoverer 构造重定向目标
- ModClassVisitorV2 - ASMModParser 构造重定向目标