我如何知道我是否正在访问 ASM 中的匿名 class?

How do I know if I am visiting an anonymous class in ASM?

我已经扩展了 ASM ClassVisitor,想知道是否在匿名 class 中访问了 class。

因为我有 class 文件,所以我认为如果 class 文件名以 $[1-9][0-9]*.class 结尾,它会匿名 class。但是货币字符在 class 名称中是有效的,因此例如一个名为 MyClass$1 的 class 将匹配(class 文件名为 MyClass$1.class),即使它不是匿名的class。我知道大多数人可能不会这样命名,但这是允许的。

所以我考虑重写 visitOuterClass 方法,看看它是否有一个外部 class 可以消除名称以 $# 结尾的外部 classes 但你仍然可以有一个内部非匿名class 以 $1 结尾的名称。

那么在 ASM 中有什么方法可以知道它正在访问一个匿名的 class?或者比我更好的把戏?

# 表示任意数字(正则表达式:[1-9][0-9]*)

相关标准是 class' InnerClasses attribute declares the class to be an anonymous inner class. ASM report the contents by calling visitInnerClass 属性的每个条目是否存在(如果存在)。

所以你可以这样检查

public class CheckForInnerClass extends ClassVisitor {
    public static void main(String[] args) throws IOException {
        Class<?>[] test={ Object.class, Map.Entry.class, new Object(){}.getClass() };
        for(Class<?> c: test) {
            new ClassReader(c.getName())
                .accept(new CheckForInnerClass(Opcodes.ASM5), ClassReader.SKIP_CODE);
        }
    }

    private String actualName;
    private Boolean anonymous;

    public CheckForInnerClass(int api) {
        super(Opcodes.ASM5);
    }
    @Override
    public void visit(int version, int access,
        String name, String signature, String superName, String[] interfaces) {
        actualName=name;
    }
    @Override
    public void visitInnerClass(String name, String outer, String innerName, int access) {
        if(name.equals(actualName)) {
            anonymous = innerName==null;
        }
    }
    @Override
    public void visitEnd() {
        System.out.println(actualName+": is "
            + (anonymous==null? "not an": anonymous? "an anonymous": "a named")
            + " inner class");
    }
}

打印

java/lang/Object: is not an inner class
java/util/Map$Entry: is a named inner class
CheckForInnerClass: is an anonymous inner class