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

时间:2014-10-01 11:20:52

标签: java linux jvm jvm-hotspot

我必须运行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分钟还没完呢。有什么想法吗?

5 个答案:

答案 0 :(得分:136)

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

jmap / jstack

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

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

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

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

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

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

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

  7. 让我们总结动态附加的好处和缺点。

    <强>赞成。

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

    <强>缺点。

    • 该工具应由同一用户(euid / egid)作为目标JVM运行。
    • 只能在实时健康的JVM上使用。
    • 如果目标JVM以-XX:+DisableAttachMechanism启动,则无效。

    jmap -F / jstack -F

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

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

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

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

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

    5. <强>赞成。

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

      <强>缺点。

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

      注意

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

答案 1 :(得分:72)

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

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

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

答案 2 :(得分:1)

如果您的应用程序作为systemd服务运行。应打开/usr/lib/systemd/system/下并以服务名称命名的服务文件。然后检查 privateTmp 属性是否为真。

如果为true,则应将其更改为false,然后按以下命令刷新服务: systemctl daemon-reload systemctl restart [servicename] 如果要在重新启动之前运行jmap / jcmd,则可以使用服务文件中的execStop脚本。只需将命令放入其中并执行systemctl stop [service name]

答案 3 :(得分:1)

通常用 -f 解决。

我遇到过full GC导致命令无法执行的情况。

答案 4 :(得分:0)

就像ben_wing所说,你可以运行:

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

(在我的情况下,用户为jboss-as,但您的用户可能是jboss或其他用户。)

但这还不够,因为它要求我输入密码[sudo] password for ec2-user:),虽然我可以运行sudo而不提示我输入其他命令的密码。

我找到了解决方案here,我只需要先添加另一个sudo

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

它也适用于jcmdjinfo等其他命令。