如何从 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.
给定一个任意 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.
以下是此类代理的示例:GetBytecode.java。
最后,如果您不介意使用本机代码,可以使用 JVMTI 函数 GetConstantPool and GetBytecodes 获取特定 Java 方法的字节码。
这里是JVMTI example.