如何从 Class 获取字节码作为字节数组

How to get bytecode as byte array from Class

给定一个任意 Class 实例,包括运行时生成的实例(磁盘上没有 .class 文件),有没有办法获得 class 字节?

String classFile = "/" + Object.class.getName().replace('.', '/') + ".class";
System.out.println(classFile);
URL url = Test.class.getResource(classFile);
System.out.println(url);

产生这个输出。

/java/lang/Object.class
jar:file:/usr/java/jdk1.8.0_60/jre/lib/rt.jar!/java/lang/Object.class

因此您可以使用 url 以字节为单位读取。 (不适用于运行时生成的 类)

一般来说,这是不可能的。在加载 class 时,JVM 解析其字节码并将其转换为内部表示。之后 JVM 可以自由地忘记原始字节码,这就是 HotSpot JVM 真正发生的事情。

然而,通过某些 hack,可以检查内部 class 表示并将其转换回有效的 class 文件(尽管它与原始字节码不同)。在 HotSpot JVM 中使用这样的过程为 Instrumentation purposes.

重建一个 class 文件

作为概念证明,我编写了 a program,它使用 Unsafe 从 JVM 内存中提取已加载 class 的已处理字节码。这仅用于演示;永远不要在生产中尝试这个。

编辑

您还可以使用 Instrumentation API. This requires a Java agent loaded either at VM bootstrap (using -javaagent VM option) or at runtime via Dynamic Attach mechanism.

获取 class 文件数据(可能被 JVM 修改)

以下是此类代理的示例:GetBytecode.java

最后,如果您不介意使用本机代码,可以使用 JVMTI 函数 GetConstantPool and GetBytecodes 获取特定 Java 方法的字节码。

这里是JVMTI example.