如何在运行时从 JVM 中提取类文件

Posted

技术标签:

【中文标题】如何在运行时从 JVM 中提取类文件【英文标题】:How to extract class files at runtime from a JVM 【发布时间】:2021-01-27 14:10:59 【问题描述】:

我的 JVM 上运行了一个 Jar 应用程序。应用程序在运行时会下载额外的.class 文件。这些被加载到应用程序的内存中(我通过堆和线程转储进行了验证)。我想提取类文件并反编译它们以查看发生了什么。

有谁知道任何工具可以保存 Jar 的确切当前状态,然后从 JVM 运行时反编译或反编译(或提取 .class 文件)?

【问题讨论】:

一个更好的主意:如果应用程序下载并运行神秘代码,而您没有充分的理由信任该应用程序:不要运行它。 “jar 的确切当前状态”永远不会改变。 jar 文件不受内存中的类的影响。您如何“通过堆和线程转储”验证是否有其他类加载到内存中? 我可以看到额外的包被加载到 JAR 的内存中。从服务器下载一个 zip 文件,然后在内存中解压缩(我猜)并加载到 jar/jvm/memory 中。 【参考方案1】:

使用JVMTI接口,可以做一个所谓的代理。对于实际传递到类加载器进行加载的每个类文件都会调用这些文件,此时您可以选择保存它。

像往常一样制作一个主应用程序,但不是psv main(String[]),而是public static void premain(String args, Instrumentation instrumentation)

用它制作一个 jar 就像你制作一个普通的 java 可运行 jar 一样,除了清单 Main-Class 条目,它是 Premain-Class

将其作为代理 (java -javaagent:yourjar.jar -therestofyouroptionsasnormal) 启动,您的 premain 将在实际 main 之前被调用一次。然后,在您如此获得的Instrumentation 实例上,调用addTransformer,传入您编写的ClassFileTransformer 实现的实例。这个转换器实际上不会转换任何东西,但它的transform 方法将被调用,让您看到正在加载的类文件。例如,如果需要,可以将它们保存到目录中。

【讨论】:

以上是关于如何在运行时从 JVM 中提取类文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在运行时从 nhibernate 映射文件生成实体类

Java方法区

从正在运行的 JVM 导出数据?

JVM 内存结构

如何在插入时从笔式驱动器运行 .exe 文件?

如何在运行时从文件中加载 HTML 模板?