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

2022-08-31 10:58:03

我必须运行才能获取我的进程的堆转储。但返回:jmapjvm

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分钟,尚未完成。任何想法为什么?

答案 1

jmap与 ,以及与 使用完全不同的机制与目标 JVM 进行通信。jmap -Fjstackjstack -F

jmap / jstack

在没有这些工具的情况下运行时,请使用动态连接机制。其工作原理如下。-F

  1. 在连接到 Java 进程 1234 之前,在目标进程的工作目录或 处创建一个文件。jmap.attach_pid1234/tmp

  2. 然后发送到目标进程。当 JVM 捕获信号并找到 时,它将启动线程。jmapSIGQUIT.attach_pid1234AttachListener

  3. AttachListenerthread 创建 UNIX 域套接字以侦听来自外部工具的命令。/tmp/.java_pid1234

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

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

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

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

优点。

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

缺点。

  • 该工具应由与目标 JVM 相同的用户 (/) 运行。euidegid
  • 只能在实时和健康的 JVM 上使用。
  • 如果目标 JVM 是使用 启动的,则将不起作用。-XX:+DisableAttachMechanism

jmap -F / jstack -F

使用工具运行时,切换到具有热点可维护性代理的特殊模式。在此模式下,目标进程被冻结;这些工具通过操作系统调试工具读取其内存,即Linux上的ptrace-F

  1. jmap -F在目标 JVM 上调用。目标进程无条件暂停以响应信号。PTRACE_ATTACHSIGSTOP

  2. 该工具使用 读取 JVM 内存。 一次只能读取一个单词,因此读取目标进程的大堆需要太多的调用。这是非常非常缓慢的。PTRACE_PEEKDATAptrace

  3. 该工具根据特定 JVM 版本的知识重建 JVM 内部结构。由于不同版本的 JVM 具有不同的内存布局,因此仅当模式来自与目标 Java 进程相同的 JDK 时才有效。-Fjmap

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

优点。

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

缺点。

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

注意

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


答案 2

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

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

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

推荐