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

ray*_*man 76 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
Run Code Online (Sandbox Code Playgroud)

所以我使用了-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 ...
Run Code Online (Sandbox Code Playgroud)
  1. 使用-F 是可以进行堆转储吗?
  2. 我等了20分钟还没完呢.有什么想法吗?

apa*_*gin 153

jmapjmap -F,以及jstackjstack -F使用完全不同的机制与目标JVM到communcate.

jmap/jstack

当不运行-F这些工具都使用动态连接机制.其工作原理如下.

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

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

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

  4. 出于安全考虑,当(从连接jmap)被接受时,JVM验证插座等的凭证是等于euidegidJVM的过程.这就是为什么jmap如果由不同的用户(甚至是root用户)运行将无法工作.

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

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

让我们总结一下Dynamic Attach的好处和缺点.

优点.

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

缺点.

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

jmap -F/jstack -F

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

  1. jmap -FPTRACE_ATTACH在目标JVM上调用.目标过程无条件地暂停以响应SIGSTOP信号.

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

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

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

优点.

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

缺点.

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

注意

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


小智 77

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

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

sudo -u jboss jmap -dump:file.bin <pid>
Run Code Online (Sandbox Code Playgroud)


小智 6

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

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


Luc*_*tto 5

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

sudo -u jboss-as jmap -dump:file.bin <pid>
Run Code Online (Sandbox Code Playgroud)

(在我的例子中,用户是jboss-as,但你的用户可能是jboss或其他用户。)

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

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

sudo sudo -u jboss-as jmap -dump:file.bin <pid>
Run Code Online (Sandbox Code Playgroud)

它也可以与其他命令一起使用,例如jcmdjinfo