ModClassVisitorV2
基本信息
| 属性 | 值 |
|---|---|
| 类 | com.mitchej123.jarjar.fml.common.discovery.asm.ModClassVisitorV2 |
| 父类 | cpw.mods.fml.common.discovery.asm.ModClassVisitor |
| 来源 | Minecraft Forge (LGPL 2.1) |
| 改写方法 | visit(int, int, String, String, String, String[]) |
ModClassVisitorV2 在 ASM 树遍历期间捕获类的 binary interfaces,转发给 ASMModParserV2 暂存;最终在 sendToTable 时作为 ASMData 加入 table。
替换链
由 V2ConstructionReplacerTransformer 在 ASMModParser(InputStream) 构造函数内把 new ModClassVisitor(discoverer) 替换为 new ModClassVisitorV2(discoverer):
} else if (className.equals(ASM_MOD_PARSER_CLASSNAME)) {
transformClass(cn, "<init>", "(Ljava/io/InputStream;)V", MOD_ANNOTATION_CLASS, MOD_ANNOTATION_V2_CLASS,
"(Lcpw/mods/fml/common/discovery/asm/ASMModParser;)V",
"(Lcom/mitchej123/jarjar/fml/common/discovery/asm/ASMModParserV2;)V");
}
visit 重写
public ModClassVisitorV2(ASMModParser discoverer) {
super(discoverer);
if (discoverer instanceof ASMModParserV2 discovererV2) {
this.discovererV2 = discovererV2;
} else {
this.discovererV2 = null;
}
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
if (discovererV2 != null) {
discovererV2.beginNewTypeName(name, version, superName, interfaces);
} else {
super.visit(version, access, name, signature, superName, interfaces);
}
}
discoverer是ASMModParserV2→discovererV2非空 → 直接调beginNewTypeName传入 interface 数组discoverer是普通ASMModParser→ 退化为super.visit,保持兼容
beginNewTypeName 在 ASMModParserV2 中
public void beginNewTypeName(String typeQName, int classVersion, String superClassQName, String[] interfaces) {
super.beginNewTypeName(typeQName, classVersion, superClassQName);
if (this.interfaces == null) this.interfaces = Sets.newHashSet();
Collections.addAll(this.interfaces, interfaces);
}
interfaces 是 Set<String>,暂存每个类实现的接口列表(去重)。
调用链
ASMModParserV2(InputStream)
→ ASMModParser.<init>(stream)
→ new ModClassVisitorV2(this) // [原]new ModClassVisitor(this)
→ ClassReader.accept(visitor, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES) // [FMLTransformer 改写]
→ visitor.visit(version, access, name, signature, superName, interfaces)
→ discovererV2.beginNewTypeName(name, version, superName, interfaces)
ClassReader.accept 的 flags 由 FMLTransformer.patchAsmModParserCtor 改为 SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES,跳过方法字节码读取——只跑常量池与 visit()。
相关条目
- ASMModParserV2 - 接收 beginNewTypeName
- V2ConstructionReplacerTransformer - 替换
new ModClassVisitor() - FMLTransformer - 配合 SKIP_CODE 等 flags