14

假设在我的 JVM 中有一个已加载的类Class<C> myClass。有没有靠谱的的方法来向 JVM 请求字节码.class 的内容?即是这样的:

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

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

任何(更好的)想法?

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

4

2 回答 2

11

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

类加载器不只是加载字节码。因此,如果您能够从 JVM 内存中获取字节码(如果您编写大量特定于实现的本机代码,这在理论上是可能的),那么远程类加载器将毫无用处。你需要给它一个实际的.class文件。

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

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

于 2013-06-26T14:20:58.293 回答
4

您可以使用 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);
    }
}
于 2015-04-23T20:58:33.947 回答