1

如何使用 ASM java Byte Code 获取一个类的所有超类?

4

3 回答 3

2
package com.eg.agent;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import org.objectweb.asm.ClassReader;

public class EgClassFileTransformer implements ClassFileTransformer {

    protected String agentArgString = "";
    protected Instrumentation instrumentation;

    public EgClassFileTransformer(String agentArgs, Instrumentation inst){
        agentArgString = agentArgs;
        instrumentation = inst;
        instrumentation.addTransformer(this);
    }

    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, 
            ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException
        {
            //System.out.println("ClassName :"+className);
            InputStream in = loader.getResourceAsStream(className.replace('.', '/') + ".class");
            try{
                ClassReader classReader=new ClassReader(in);
                String superClassName = classReader.getSuperName();
                String[] interfaces = classReader.getInterfaces();
                if(interfaces!=null && interfaces.length > 0){
                    for(int k=0;k<interfaces.length;k++){
                        String inface = interfaces[k];
                        System.out.println(" \t interface :"+inface);
                    }
                }
                //System.out.println("superClassName :"+superClassName);
                ArrayList thisList = new ArrayList();
                thisList.add(superClassName);
                ArrayList superList = printSuperClassNames(superClassName , thisList);
                System.out.println("className :"+className +" ==>"+ " superList :"+superList);
            } catch (IOException e) {
                //e.printStackTrace();
                System.out.println("[EXECEPTION] ..."+className);
            }
            return null;
        }

    public static ArrayList printSuperClassNames(String className, ArrayList list)
    {
        ClassReader cr=null;
        try {
            cr = new ClassReader(className);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        String superName = cr.getSuperName();
        //System.out.println("[superName]"+superName);
        if(superName!=null && !superName.equals("java/lang/Object"))
        {
            list.add(superName);
            String superClass = superName.replace('.', '/');
            printSuperClassNames(superClass, list);
        }
        return list;
    }
}
于 2013-02-13T08:30:59.440 回答
0

一个简单的方法是访问一个类的构造函数的字节码并记录第一个构造函数调用指令,即invokespecial你可以找到的调用。这应该为您提供super与当前感兴趣的类相关的类的名称。

于 2013-02-05T10:37:12.027 回答
0

这有点棘手,因为类文件只包含直接超类。因此,您必须递归地阅读所有超类。

您可以通过使用 ClassVisitor 处理每个类来执行此操作,该 ClassVisitor 具有覆盖的访问(int 版本,int 访问,字符串名称,字符串签名,字符串超名称,字符串 [] 接口)方法来读取超类名称。

伪代码:

List<String> getSuperClasses(className){
  superClass=getSuperClass(className)
  return superClass+getSuperClasses(superClass)
}

String getSuperClass(className) {
  cw=new ClassWriter()
  v=new SuperClassReadingClassVisitor(cw)
  new ClassReader(className).accept(v)
  return v.superClass
}

class SuperClassReadingClassVisitor{
  String superClass
  @Override
  visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
  superClass=superName
  super.visit(version, access, name, ...)
}
于 2013-02-06T06:48:48.423 回答