从加载的类中获取字节码

时间:2013-06-26 13:13:10

标签: java class classloader

假设在我的JVM中我有一个加载的类Class<C> myClass。是否有可靠的方式向JVM询问.class的 bytecode 内容?即像这样的东西:

<C> byte[] getClassBytecode(Class<C> myClass) {
    return /* the contents of the .class resource where C was loaded from */;
}

(显然InputStreambyte[]一样好。我知道我可以使用myClass.getResource()(和朋友)来获取类文件,但是通过敲击类名来获取一个提供给getResource的URL会感觉不对。此外,我不确定如果动态生成C(例如使用javax.tools.JavaCompiler),这会如何表现。

任何(更好)的想法?

注意:目标是能够将字节码类推送到不同的JVM并使用自定义类加载器将其加载到那里

2 个答案:

答案 0 :(得分:7)

  

注意:目标是能够在不同的JVM上使用自定义类加载器加载字节码

类加载器doesn't just load bytecode。因此,如果你 能够从JVM内存中获取字节码(理论上如果你编写了很多特定于实现的本机代码,那么这对你的远程类加载器来说是没用的)。您需要为其提供一个实际的.class文件。

Class.getResource()是完成此任务的最佳方式。因为它与调用类看起来在同一个包中,所以你需要做的就是使用类的简单名称,追加“.class”然后就完成了。

如果你有内部或嵌套类,它确实变得有点困难,但这是一个你必须处理的实现细节(如果你推动初始类,你仍然需要拉取任何依赖类)。

答案 1 :(得分:2)

您可以使用ASM库来获取类的详细字节码。示例代码如下。

     public class AAA extends ClassLoader{
       public static void main(){
        String resource = caller.replace('.', '/')+".class";
        InputStream is = getResourceAsStream(resource);
        ClassReader cr = new ClassReader(is);
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);

        ClassVisitor visitor = new BCMerge(Opcodes.ASM5, cw, callee);
        cr.accept(visitor, 0);
    }
  }
  class BCMerge extends ClassVisitor{
         public MethodVisitor visitMethod(int access, String name, String desc,String signature, String[] exceptions) {
        System.out.println(name);
        if (cv != null) {
            return new MyMethodVisit(cv.visitMethod(access, name, desc, signature, exceptions));
        }
        return null;
    }
   }

public class MyMethodVisit extends MethodVisitor{
    @Override
    public void visitMethodInsn(int opcode, String owner, String name,
            String desc, boolean itf) {
            System.out.println("opcode:" + opcode + " owner:" + owner + " name:"+ name + " desc:" + desc);
            return super.visitMethodInsn(opcode, owner, name, desc, itf);
    }
}