【问题标题】:How to use ASM ClassVisitor.visitOuterClass?如何使用 ASM ClassVisitor.visitOuterClass?
【发布时间】:2021-10-17 07:34:05
【问题描述】:

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

  1. 模拟器类
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 没有被调用,我想知道为什么?

我们将不胜感激。

【问题讨论】:

标签: java class java-bytecode-asm


【解决方案1】:

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

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

所以当你把例子改为

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

    static class StaticNestedClass{

    }
}

并解析OuterClass$1InnerClass,你会得到一个带有OuterClasssomeMethod(Ljava/lang/String;)V参数的visitOuterClass的调用,完全识别封闭的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    • 1970-01-01
    相关资源
    最近更新 更多