假设在我的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 */;
}
(显然InputStream
与byte[]
一样好。我知道我可以使用myClass.getResource()
(和朋友)来获取类文件,但是通过敲击类名来获取一个提供给getResource的URL会感觉不对。此外,我不确定如果动态生成C
(例如使用javax.tools.JavaCompiler
),这会如何表现。
任何(更好)的想法?
注意:目标是能够将字节码类推送到不同的JVM并使用自定义类加载器将其加载到那里
答案 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);
}
}