如何使用 ASM 访问内部 类 的方法?

How to access methods of inner classes using ASM?

我正在尝试打印出 .class 文件中所有方法的说明。下面的代码仅打印出外部 class 方法 (main) 的指令。

如何访问 classes 的内部方法?我读到我可以像加载外部 class 一样加载内部 class。我该怎么做?

import java.io.InputStream;
import java.io.FileInputStream;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.util.List;
import org.objectweb.asm.*;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.util.*;

public class ClassInfoReader {

    public static void main(String[] args) throws Exception{
        InputStream in = new FileInputStream("MyInfo.class");
        ClassReader reader = new ClassReader(in);
        ClassNode classNode = new ClassNode();
        reader.accept(classNode,0);
        @SuppressWarnings("unchecked")
        final List<MethodNode> methods = classNode.methods;
        for(MethodNode m: methods){
             InsnList inList = m.instructions;
             System.out.println(m.name);
             for(int i = 0; i< inList.size(); i++){
                 System.out.print(insnToString(inList.get(i)));
             }
        }

        final List<InnerClassNode> classes = classNode.innerClasses;
        System.out.println(classes);
        for(InnerClassNode c: classes){
             System.out.println(c.innerName);
        }
    }

    public static String insnToString(AbstractInsnNode insn){
        insn.accept(mp);
        StringWriter sw = new StringWriter();
        printer.print(new PrintWriter(sw));
        printer.getText().clear();
        return sw.toString();
    }

    private static Printer printer = new Textifier();
    private static TraceMethodVisitor mp = new TraceMethodVisitor(printer);

这部分代码只展示了内部classes的基本信息,例如内部 classes 的名称,外部 class 的名称和访问标志。

final List<InnerClassNode> classes = classNode.innerClasses;
        for(InnerClassNode c: classes){
             System.out.println(c.innerName);
        } 

嵌套的 class 不是原始 Java 的一部分。它们仅在 Java 1.1 中添加,因此必须对现有的 class 文件格式进行改造。因此,在字节码级别,嵌套的 classes 只是单独 class 文件中的普通 classes。唯一区别它们的是几个元数据属性,这些属性包含有关源级别嵌套 classes 的信息,用于反射和编译。

因此访问嵌套 class 的方法是加载它并像处理任何其他 class 一样处理它。您已经知道如何获取嵌套 class 的名称,现在您只需要创建一个新的 ClassFileReader 并递归加载它们中的每一个。