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()。

相关条目