如何使用ASM ClassVisitor.visitOuterClass?

How to use ASM ClassVisitor.visitOuterClass?

我正在研究ASM,我想用ClassVisitor打印一个class的信息,现在不知道什么时候调用visitOuterClass方法。这是我的代码。

  1. 模拟器class
public class OuterClass {
    class InnerClass {
        class InnerA{
        }
    }

    static class StaticNestedClass{

    }

}
  1. ClassVisitor实现和测试代码
public class ASMMain {


    public static class ParsingVisitor extends ClassVisitor {
        public ParsingVisitor() {
            super(Opcodes.ASM9);
        }

        public ParsingVisitor(ClassVisitor classVisitor) {
            super(Opcodes.ASM9, classVisitor);
        }

        @Override
        public void visitSource(String source, String debug) {
            super.visitSource(source, debug);
            System.out.println("visitSource===" + source + "===" + debug);
        }

        @Override
        public ModuleVisitor visitModule(String name, int access, String version) {
            System.out.println("visitModule===" + name + "===" + access + "===" + version);
            return super.visitModule(name, access, version);
        }

        @Override
        public void visitNestHost(String nestHost) {
            super.visitNestHost(nestHost);
            System.out.println("visitNestHost===" + nestHost);
        }

        @Override
        public void visitOuterClass(String owner, String name, String descriptor) {
            super.visitOuterClass(owner, name, descriptor);
            System.out.println("visitOuterClass===" + owner + "===" + name + "===" + descriptor);
        }

        @Override
        public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
            System.out.println("visitAnnotation===" + descriptor + "===" + visible);
            return super.visitAnnotation(descriptor, visible);
        }

        @Override
        public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) {
            System.out.println("visitTypeAnnotation===" + typeRef + "===" + typePath + "===" + descriptor + "===" + visible);
            return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
        }

        @Override
        public void visitAttribute(Attribute attribute) {
            super.visitAttribute(attribute);
            System.out.println("visitAttribute===" + attribute);
        }

        @Override
        public void visitNestMember(String nestMember) {
            super.visitNestMember(nestMember);
            System.out.println("visitNestMember===" + nestMember);
        }

        @Override
        public void visitPermittedSubclass(String permittedSubclass) {
            super.visitPermittedSubclass(permittedSubclass);
            System.out.println("visitPermittedSubclass===" + permittedSubclass);
        }

        @Override
        public void visitInnerClass(String name, String outerName, String innerName, int access) {
            super.visitInnerClass(name, outerName, innerName, access);
            System.out.println("visitInnerClass===" + name + "===" + outerName + "===" + innerName + "===" + access);
        }

        @Override
        public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) {
            System.out.println("visitRecordComponent===" + name + "===" + descriptor + "===" + signature);
            return super.visitRecordComponent(name, descriptor, signature);
        }

        @Override
        public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
            System.out.println("visitField===" + access + "===" + name + "===" + descriptor + "===" + signature + "===" + value);


            return super.visitField(access, name, descriptor, signature, value);
        }

        @Override
        public void visitEnd() {
            super.visitEnd();
            System.out.println("visitEnd===");
        }
    }

    public static void main(String[] args) throws IOException {
        String filePath = "src/main/java/cn/sensorsdata/asm/";
        File file = new File(filePath + "OuterClass$InnerClass.class");
        byte[] bytes = FileUtils.readFileToByteArray(file);
        ClassReader classReader = new ClassReader(bytes);
        classReader.accept(new ParsingVisitor(), 0);

    }

}

OuterClass$InnerClassjavac OuterClass.java 命令输出。

当我运行测试代码时,visitOuterClass没有被调用,我想知道为什么?

任何帮助将不胜感激。

通过 visitInnerClass 的调用报告嵌套关系。我想,您已经注意到在解析 OuterClass$InnerClass 时,针对 OuterClassOuterClass$InnerClass 关系以及 OuterClass$InnerClassOuterClass$InnerClass$InnerA 调用了该方法] class.

方法 visitOuterClass 有不同的用途和一个非常容易误导的名称。它用于访问本地 class.

的封闭 方法

因此当您将示例更改为

public class OuterClass {
    void someMethod(String s) {
        class InnerClass {
        }
    }

    static class StaticNestedClass{

    }
}

并解析 OuterClassInnerClass,你将得到一个带有参数 OuterClasssomeMethod(Ljava/lang/String;)VvisitOuterClass 调用,完全识别封闭方法。