java - 如何使用ASM ClassVisitor.visitOuterClass?

标签 java class java-bytecode-asm

我正在学习ASM,我想使用ClassVisitor来打印类的信息,现在我不知道什么时候visitOuterClass方法会被调用。这是我的代码。

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

    static class StaticNestedClass{

    }

}
  • 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 - OuterClass$InnerClass 关系以及 OuterClass$InnerClass 调用了该方法—OuterClass$InnerClass$InnerA 解析 OuterClass$InnerClass 类时。

    方法visitOuterClass有不同的目的和一个非常具有误导性的名称。它用于访问本地类的封闭方法

    因此,当您将示例更改为

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

    并解析OuterClass$1InnerClass,您将获得对visitOuterClass的调用,参数为OuterClasssomeMethod ,和(Ljava/lang/String;)V,完全识别封闭方法。

    关于java - 如何使用ASM ClassVisitor.visitOuterClass?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68782674/

    相关文章:

    使用 ASM 或 CGLib 的 Java 依赖注入(inject)

    java - 列出从一个方法中调用的所有未实现的方法

    eclipse - 无法安装asm框架和字节码大纲插件

    java - 如何打印带有swing组件的JPanel?

    java - 嵌套类与单独的类文件

    python - 构建类以迭代返回的结构

    objective-c - Objective C类之间的通信

    java - scala 模式匹配

    java - 我需要恢复一个 Activity 实例

    Java:我正在使用 File 并创建了一个类 FileHelper 并在网页中使用 JSP 调用它......帮助?