从Java进程里dump出类的字节码文件

-
-
2026-01-30

使用 Arthas dump 命令从 Java 进程导出类字节码文件完整指南

1. 概述

dump 命令是 Arthas 提供的强大功能之一,它允许你将 JVM 中已加载的类字节码文件导出到本地磁盘。这对于以下场景非常有用:

  • 调试和分析: 检查运行时类的实际字节码,确认是否是预期的版本。
  • 逆向工程: 获取生产环境中的类文件,以便进行反编译查看源代码。
  • 问题排查: 验证热部署或类加载是否成功,以及是否加载了错误的类版本。

2. 前提条件

  • 下载 Arthas 启动器:

    arthas-install

    curl -O https://arthas.aliyun.com/arthas-boot.jar

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.

解决方案:

  1. 查找类加载器哈希: 使用 sc -d <full_class_name> 命令查看目标类的详细信息,包括其 classloader hash

    sc -d com.example.project.domain.MyBusinessObject

    在输出中找到 classloader hash 字段,例如 classloader hash: 12345678

  2. 指定类加载器进行 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

或者

exit

9. 总结与最佳实践

  • 优先使用精确匹配或包名前缀匹配: 尽量缩小 dump 范围,避免导出不必要的类。
  • 使用 --limit NNNNN 解除限制: 当匹配到大量类时,务必使用一个足够大的正数来确保所有类都被导出。
  • 注意磁盘空间: 导出大量类文件可能会占用大量磁盘空间。
  • 了解类加载器: 在复杂环境中,如果遇到类加载器歧义,学会使用 sc -d-c 选项。
  • 及时反编译: 导出 .class 文件后,使用合适的工具进行反编译以查看源代码。

目录