使用 ASM 访问 class 时,如何在不加载任何 class 的情况下知道该 class 的祖先 class?

When visiting a class using ASM, how to know the ancestor class of that class without loading any class?

我想做的是:我有一个ClassVisitor适配器,当进入visit方法时,我想知道class AncestorClass是否是祖先class 那个 class?我试过像这样使用反射(Class.forname(...)):

MyTransformer.class:

public class MyTransformer implements ClassFileTransformer {

    public byte[] transform(ClassLoader loader, String className,
                            Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
                            byte[] classfileBuffer) throws IllegalClassFormatException {

        if (className == null){
            return classfileBuffer;
        }
        ClassReader cr = new ClassReader(classfileBuffer);
        ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
        CollectionCVAdapter mca = new MyCVAdapter(cw, className);
        cr.accept(mca, 0);
        return cw.toByteArray();
    }
}

MyCVAdapter.class:

class MyCVAdapter extends ClassVisitor {

    private String className;
    private boolean isDescendantClass;

    CollectionCVAdapter(ClassVisitor classVisitor, String className){
        super(Opcodes.ASM5, classVisitor);
        this.className = className;
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        // check if this class is a descendant class of AncestorClass.class
        try{
            Class superClass = Class.forName(superName.replace("/", "."));
            do {
                if (superClass == AncestorClass.class) {
                    this.isDescendantClass= true;
                    break;
                }
                superClass = superClass.getSuperclass();
            } while (superClass != null);
        }catch (Exception e){
            e.printStackTrace();
        }
        super.visit(version, access, name, signature, superName, interfaces);
    }
    ...
}

但问题是我还想检测被检测 class 的父 class。我发现一旦Class.forName()加载父class,父class就不会进入transform方法。这意味着不能再对父 class 进行检测。那么有没有其他方法可以找出 class 是否是 AncestorClass 的后代 class?

感谢@JohannesKuhn和@Holger,终于找到了静态分析继承关系的方法

    @Override
    public void visit(int version, int access, String name, String signature, String superSlashName, String[] interfaces) {
        String originalSuperName = superSlashName;
        // check if this class is a subclass of AncestorClass.class
        try{
            while (superSlashName != null){
                if (superSlashName.equals(AncestorClassName)){
                    this.isDescendantClass= true;
                    break;
                }else{
                    InputStream is = this.loader.getResourceAsStream(superSlashName + ".class");
                    byte[] superBytes = FileUtil.loadByteCode(is);
                    ClassReader parentCr = new ClassReader(superBytes);
                    superSlashName = parentCr.getSuperName();
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        super.visit(version, access, name, signature, originalSuperName, interfaces);
    }