2

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

4

2 回答 2

11

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

但是,通过某些 hack,可以检查内部类表示并将其转换回有效的类文件(尽管它与原始字节码不同)。HotSpot JVM 中使用此类过程来重构类文件以用于检测目的

作为概念证明,我编写了一个程序,该程序使用Unsafe. 这仅用于演示;永远不要在生产中尝试这个。

编辑

您还可以使用Instrumentation API获取类文件数据(可能由 JVM 修改) 。这需要在 VM 引导程序(使用-javaagentVM 选项)或在运行时通过动态附加机制加载 Java 代理。

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

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

这是一个JVMTI 示例

于 2016-01-28T21:05:08.777 回答
2
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以字节为单位读取。(不适用于运行时生成的类)

于 2016-01-28T20:56:12.513 回答