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

クラスファイルには直接のスーパークラスしか含まれていないため、これは少し注意が必要です。したがって、すべてのスーパー クラスを再帰的に読み取る必要があります。

これを行うには、オーバーライドされた visit(int version, int access, String name, String signature, String superName, String[] interfaces) メソッドを使用して ClassVisitor で各クラスを処理し、スーパー クラス名を読み取ります。

疑似コード:

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 に答える
0

これを行う簡単な方法の 1 つは、クラスのコンストラクターのバイトコードにアクセスし、最初のコンストラクター呼び出し命令 (つまり、invokespecial見つけた呼び出し) を記録することです。superこれにより、現在関心のあるクラスに属するクラスの名前が得られるはずです。

于 2013-02-05T10:37:12.027 に答える