使用 Arthas dump 命令从 Java 进程导出类字节码文件完整指南※
1. 概述※
dump 命令是 Arthas 提供的强大功能之一,它允许你将 JVM 中已加载的类字节码文件导出到本地磁盘。这对于以下场景非常有用:
- 调试和分析: 检查运行时类的实际字节码,确认是否是预期的版本。
- 逆向工程: 获取生产环境中的类文件,以便进行反编译查看源代码。
- 问题排查: 验证热部署或类加载是否成功,以及是否加载了错误的类版本。
2. 前提条件※
下载 Arthas 启动器:
curl -O https://arthas.aliyun.com/arthas-boot.jar
启动 Arthas 并连接到目标进程:
# 请确保你以 root 用户(或者启动目标 Java 进程的用户)运行此命令 java -jar arthas-boot.jar运行后,Arthas 会列出当前系统上所有运行的 Java 进程。你需要输入目标进程的 PID 对应的序号,然后按回车。
3. dump 命令基础用法※
dump 命令的基本语法是 dump [options] <class-pattern>。
3.1 导出单个类文件※
如果你知道要导出的具体类名,可以直接指定它。
命令示例:
假设你想要导出 com.example.project.domain.MyBusinessObject 这个类:
dump com.example.project.domain.MyBusinessObject或者使用 -E 选项(正则表达式模式):
dump -E 'com.example.project.domain.MyBusinessObject'输出示例:
Dumping class com.example.project.domain.MyBusinessObject to /home/user/arthas-output/2026-01-30-10-30-00/com/example/project/domain/MyBusinessObject.class
Affect(row-cnt:1) cost in 12 ms.这会把 MyBusinessObject.class 文件导出到 Arthas 启动目录下的 arthas-output/<timestamp>/com/example/project/domain/ 路径中。
4. dump 命令高级用法:导出多个类或整个包※
通常,我们更希望导出某个包下的所有类,或者匹配特定模式的类。dump 命令支持使用通配符或正则表达式。
4.1 导出指定包下的所有类 (推荐)※
这是最常用且推荐的方式。你需要根据你的应用程序的包名来指定。
命令示例:
假设你的应用程序所有核心类都在 com.example.project 包下,你可以使用正则表达式来匹配:
dump -E 'com.example.project.*'注意:
-E选项表示后面的模式是一个正则表达式。.*表示匹配任意字符任意次数。
4.2 解决 "Found more than 50 class" 限制问题※
当你尝试导出大量类(例如整个包)时,Arthas 可能会出于性能和安全考虑,默认限制一次性导出的类数量(通常是 50 个)。你会看到类似以下提示:
Affect(row-cnt:0) cost in 63 ms.
Found more than 50 class for: com.example.project.*, Please Try to specify the classloader with the -c option, or try to use --limit option.这表明 Arthas 检测到匹配的类超过 50 个,并停止了操作。为了解决这个问题,你需要使用 --limit 选项来解除或增加这个限制。
解决方案:
使用一个足够大的正数来作为 limit 值,以确保所有匹配的类都能被导出。
dump -E 'com.example.project.*' --limit 99999解释:
--limit 99999:将导出类的数量限制设置为 99999。这个值通常足够大,可以覆盖一个应用程序中的所有类。
关于 --limit -1 的说明: 在某些 Arthas 版本或特定环境下,--limit -1 旨在取消限制,但可能不会按预期工作,甚至会报错 Found more than -1 class。因此,推荐使用一个足够大的正数(如 99999)来代替 -1。
4.3 导出所有已加载的类 (慎用)※
如果你确实需要导出 JVM 中所有已加载的类,可以使用 .* 来匹配所有类名。但请注意,这会产生大量的 .class 文件,耗时且占用磁盘空间,通常不推荐。
命令示例:
dump -E '.*' --limit 99999注意: 即使是导出所有类,也需要加上 --limit 选项来解除默认的 50 个类限制。
5. 处理类加载器歧义 (-c 选项)※
在某些复杂的应用场景(如 Web 服务器中的多个 Web 应用,或者 OSGi 容器),同一个类名可能被不同的类加载器加载了多次。如果 Arthas 无法确定要 dump 哪个类,它可能会提示你指定类加载器:
Found more than one class for: com.example.MyClass, Please specify classloader with the -c option.解决方案:
查找类加载器哈希: 使用
sc -d <full_class_name>命令查看目标类的详细信息,包括其classloader hash。sc -d com.example.project.domain.MyBusinessObject在输出中找到
classloader hash字段,例如classloader hash: 12345678。指定类加载器进行 dump:
dump -E 'com.example.project.*' --limit 99999 -c 12345678将
12345678替换为你实际查到的classloader hash。
6. dump 结果查看※
dump 命令执行成功后,Arthas 会在命令行中输出每个被 dump 文件的保存路径。
默认保存路径: 导出的 .class 文件通常保存在 Arthas 启动目录下的 arthas-output/ 文件夹中。该文件夹下会按时间戳创建子目录,例如 arthas-output/2026-01-30-10-30-00/,然后类文件会按照其包结构存放。
示例路径: /home/user/arthas-output/2026-01-30-10-30-00/com/example/project/domain/MyBusinessObject.class
7. 后续操作:反编译 .class 文件※
导出的 .class 文件是 Java 字节码,不可直接阅读。你需要使用 Java 反编译工具将其转换为可读的 Java 源代码。
常用的 Java 反编译工具:
- JD-GUI: 一个流行的图形界面反编译工具。
- Luyten: 另一个功能强大的图形界面反编译工具,基于 Procyon。
- Fernflower: IntelliJ IDEA 内置的反编译器,也可以作为独立工具使用。
- CFR: 命令行反编译器,功能强大。
8. 完成操作后退出 Arthas※
当你完成所有 dump 操作后,可以通过以下命令退出 Arthas 命令行界面:
quit或者
exit9. 总结与最佳实践※
- 优先使用精确匹配或包名前缀匹配: 尽量缩小
dump范围,避免导出不必要的类。 - 使用
--limit NNNNN解除限制: 当匹配到大量类时,务必使用一个足够大的正数来确保所有类都被导出。 - 注意磁盘空间: 导出大量类文件可能会占用大量磁盘空间。
- 了解类加载器: 在复杂环境中,如果遇到类加载器歧义,学会使用
sc -d和-c选项。 - 及时反编译: 导出
.class文件后,使用合适的工具进行反编译以查看源代码。