运行 jmap 获取无法打开套接字文件

新手上路,请多包涵

我必须运行 jmap 才能对我的进程进行堆转储。但是 jvm 返回:

 Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding

所以我使用了 -F

 ./jmap -F -dump:format=b,file=heap.bin 10330
Attaching to process ID 10331, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.51-b03
Dumping heap to heap.bin ...

  1. 使用 -F 可以进行堆转储吗?
  2. 我等了 20 分钟,还没有完成。任何想法为什么?

原文由 rayman 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答

jmap vs. jmap -F , as well as jstack vs. jstack -F use completely different mechanisms to communcate with the target JVM.

jmap / jstack

在没有 -F 的情况下运行时,这些工具使用 Dynamic Attach Mechanism 。这工作如下。

  1. 在连接到Java进程1234之前, jmap 创建一个文件 .attach_pid1234 /tmp

  2. 然后 jmap 发送 SIGQUIT 到目标进程。当 JVM 捕捉到信号并找到 .attach_pid1234 时,它会启动 AttachListener 线程。

  3. AttachListener 线程创建 UNIX 域套接字 /tmp/.java_pid1234 监听来自外部工具的命令。

  4. 出于安全原因,当接受连接(来自 jmap )时,JVM 会验证套接字对等方的凭据是否等于 JVM 进程的 euidegid 。这就是为什么 jmap 如果由不同的用户(甚至是 root)运行将不起作用。

  5. jmap 连接到socket,并发送 dumpheap 命令。

  6. 该命令由JVM的 AttachListener 线程读取并执行。所有输出都被发送回套接字。由于堆转储是由 JVM 直接在进程内进行的,因此操作非常快。但是,JVM 只能在安全点执行此 操作。如果无法到达安全点(例如进程挂起、无响应或长时间 GC 正在进行), jmap 将超时并失败。

让我们总结一下动态附加的优点和缺点。

优点。

  • 堆转储和其他操作由 JVM 以最大速度协同运行。
  • 您可以使用任何版本的 jmapjstack 连接到任何其他版本的 JVM。

缺点。

  • 该工具应由与目标 JVM 相同的用户( euid / egid )运行。
  • 只能在运行良好的 JVM 上使用。
  • 如果目标 JVM 以 -XX:+DisableAttachMechanism 启动,则将无法工作。

jmap -F / jstack -F

当使用 -F 运行时,工具会切换到具有 HotSpot Serviceability Agent 的特殊模式。在这种模式下,目标进程被冻结;这些工具通过操作系统调试工具读取其内存,即 Linux 上的 ptrace

  1. jmap -F PTRACE_ATTACH 。目标进程响应 SIGSTOP 信号无条件挂起。

  2. 该工具使用 PTRACE_PEEKDATA 读取 JVM 内存。 ptrace 一次只能读取一个字,所以读取目标进程的大堆需要调用太多。这是非常非常缓慢的。

  3. 该工具基于特定 JVM 版本的知识重构 JVM 内部结构。由于不同版本的 JVM 有不同的内存布局, -F 模式只有在 jmap 来自与目标 Java 进程相同的 JDK 时才有效。

  4. 该工具自己创建堆转储,然后恢复目标进程。

优点。

  • 不需要来自目标 JVM 的合作。甚至可以在挂起的进程上使用。
  • ptrace 只要操作系统级别的权限足够,就可以工作。例如 root 可以转储所有其他用户的进程。

缺点。

  • 大堆非常慢。
  • 工具和目标进程应该来自同一版本的JDK。
  • 当工具以强制模式连接时,无法保证安全点。尽管 jmap 尝试处理所有特殊情况,但有时可能会发生目标 JVM 处于不一致状态的情况。

笔记

有一种更快的方法可以在强制模式下进行堆转储。首先,使用 gcore 创建一个 coredump,然后在生成的核心文件上运行 jmap 。请参阅 相关问题

原文由 apangin 发布,翻译遵循 CC BY-SA 3.0 许可协议

我刚刚发现 jmap (可能是 jvisualvm 在使用它生成堆转储时)强制运行 jmap 的用户必须是运行试图被转储的进程的同一用户。

在我的情况下,我想要一个堆转储的 jvm 正在由 linux 用户“jboss”运行。所以在 sudo jmap -dump:file.bin <pid> 报告“无法打开套接字:”的地方,我能够使用以下方法获取我的堆转储:

 sudo -u jboss jmap -dump:file.bin <pid>

原文由 ben_wing 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题