运行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分钟,还没有完成。 任何想法为什么?

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

jmap / jstack

当运行没有-F这些工具使用dynamic连接机制 。 这工作如下。

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

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

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

  4. 出于安全原因,当接受来自jmap的连接时,JVM将validation对等端的凭证是否等于JVM进程的euidegid 。 这就是为什么如果由不同的用户(即使是root)运行jmap也不行。

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

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

我们来总结dynamic连接的优点和缺点。

优点。

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

缺点。

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

jmap -F / jstack -F

当使用-F运行时,工具切换到以HotSpot可维护性代理程序为特色的特殊模式。 在这种模式下,目标进程被冻结; 这些工具通过OSdebugging工具读取它的内存,也就是Linux上的ptrace

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

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

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

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

优点。

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

缺点。

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

注意

在强制模式下有更快的堆转储方法。 首先,用gcore创build一个coredump,然后在生成的核心文件上运行jmap 。 看到相关的问题 。

我刚刚发现,jmap(当使用它来生成堆转储时,大概是jvisualvm)强制运行jmap的用户必须是运行该进程的同一用户,试图转储。

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

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

就像ben_wing说的那样,你可以运行:

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

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

但这还不够,因为它向我提供了一个密码[sudo] password for ec2-user: ,尽pipe我可以运行sudo而不用提示其他命令input密码。

我在这里find了解决scheme,我只需要首先添加另一个sudo

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

它也可以和其他命令一起使用,比如jcmdjinfo