使用ASM java Byte Code的类的所有超类

时间:2013-02-05 04:46:48

标签: java-bytecode-asm

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

3 个答案:

答案 0 :(得分: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;
    }
}

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

您可以通过使用ClassVisitor处理每个类来执行此操作,并使用重写访问(int version,int access,String name,String signature,String superName,String [] interfaces)方法来读取超类名称。

伪代码:

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, ...)
}