EarlyAccessTransformer
基本信息
| 属性 | 值 |
|---|---|
| 类 | com.mitchej123.jarjar.rfb.transformer.EarlyAccessTransformer |
| Transformer ID | jarjar-earlyaccesstransformer |
| RFB 排序 | sortBefore = ["*"] — 最先运行 |
| 目标类(7 个) | CoreModManager, CoreModManager.FMLPluginWrapper, CoreModManager$FMLPluginWrapper, ModListHelper, FMLInjectionData, ModCandidate, MetadataCollection |
FML 1.7.10 的访问层级是 package-private,JarJar 的 V2 类需要访问这些字段/方法/内部类。Source-level jarjar_at.cfg 只在 access transformer 加载后生效,而 transformer 自身就需要这些字段,因此 JarJar 在 ASM 字节码层把它们改为 public。
操作
public void transformClass(loader, context, manifest, className, classNode) {
final ClassNode cn = classNode.getNode();
if (cn == null || cn.fields == null) return;
cn.access &= ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
cn.access |= Opcodes.ACC_PUBLIC;
for (FieldNode field : cn.fields) {
field.access &= ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
field.access |= Opcodes.ACC_PUBLIC;
}
if (cn.methods != null) {
for (MethodNode method : cn.methods) {
method.access &= ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
method.access |= Opcodes.ACC_PUBLIC;
}
}
if (cn.innerClasses != null) {
for (InnerClassNode innerClass : cn.innerClasses) {
if (innerClass.name.endsWith("FMLPluginWrapper")) {
innerClass.access &= ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
innerClass.access |= Opcodes.ACC_PUBLIC;
}
}
}
}
仅命中目标
shouldTransformClass 用 TARGET_CLASSES.contains(className) 限定,避免对所有类做无谓扫描。
private static final Set<String> TARGET_CLASSES = ImmutableSet.of(
"cpw.mods.fml.relauncher.CoreModManager",
"cpw.mods.fml.relauncher.CoreModManager.FMLPluginWrapper",
"cpw.mods.fml.relauncher.CoreModManager$FMLPluginWrapper",
"cpw.mods.fml.relauncher.ModListHelper",
"cpw.mods.fml.relauncher.FMLInjectionData",
"cpw.mods.fml.common.discovery.ModCandidate",
"cpw.mods.fml.common.MetadataCollection");
设计意图
jarjar_at.cfg 中虽然也声明了同样的字段为 public,但 access transformer 必须等到 cpw.mods.fml.common.asm.transformers.ModAccessTransformer 加载,晚于 JarJar 自己的 transformer。所以 JarJar 必须用 ASM 直接修改访问标志。
后续 transformer(FMLTransformer、V2ConstructionReplacerTransformer)依赖这一修改后的可见性才能调用 INVOKESTATIC CoreModManager.somePrivate(...)。
相关条目
- RFB 插件入口 - 注册该 transformer
- FMLTransformer - 利用该 transformer 公开的方法
- V2ConstructionReplacerTransformer - 利用该 transformer 公开的类
- JarJar 配置文件 - 与 jarjar_at.cfg 的层级关系