从加载的类中获取字节码

2022-09-04 03:01:07

假设在我的JVM中,我有一个加载的类。有没有可靠的方法向JVM询问.class的字节码内容?即:Class<C> myClass

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

(显然,一个会和一样好)。我知道我可以使用(和朋友)来获取类文件,但是锤击类名以获取要获取的URL以获取GetResource感觉不对。另外,我不确定如果这是动态生成的(例如使用),这将如何表现。InputStreambyte[]myClass.getResource()Cjavax.tools.JavaCompiler

任何(更好)的想法?

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


答案 1

注意:目标是能够在不同的JVM上使用定制类装入器装入字节码

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

Class.getResource() 是完成此任务的最佳方式。由于它看起来与调用类位于同一包中,因此您需要做的就是获取该类的简单名称,附加“.class”即可完成。

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


答案 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);
    }
}