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)
-F 是可以进行堆转储吗?apa*_*gin 153
jmap对jmap -F,以及jstack对jstack -F使用完全不同的机制与目标JVM到communcate.
当不运行-F这些工具都使用动态连接机制.其工作原理如下.
在连接到Java进程1234之前,在目标进程的工作目录或at处jmap创建一个文件..attach_pid1234/tmp
然后jmap发送SIGQUIT到目标进程.当JVM捕获信号并找到时.attach_pid1234,它会启动AttachListener线程.
AttachListener线程创建UNIX域套接字/tmp/.java_pid1234以侦听来自外部工具的命令.
出于安全考虑,当(从连接jmap)被接受时,JVM验证插座等的凭证是等于euid和egidJVM的过程.这就是为什么jmap如果由不同的用户(甚至是root用户)运行将无法工作.
jmap连接到套接字,并发送dumpheap命令.
该命令由AttachListenerJVM 的线程读取和执行.所有输出都被发送回套接字.由于堆转储是由JVM直接在进程中进行的,因此操作非常快.但是,JVM只能在安全点执行此操作.如果无法达到安全点(例如,进程挂起,没有响应,或者GC正在进行中),jmap则会超时并失败.
让我们总结一下Dynamic Attach的好处和缺点.
优点.
jmap或jstack连接到任何其他版本的JVM.缺点.
euid/ egid)运行.-XX:+DisableAttachMechanism.使用-F工具运行时,切换到具有HotSpot Serviceability Agent功能的特殊模式.在此模式下,目标进程被冻结; 这些工具通过OS调试工具读取其内存,即ptrace在Linux上.
jmap -FPTRACE_ATTACH在目标JVM上调用.目标过程无条件地暂停以响应SIGSTOP信号.
该工具使用读取JVM内存PTRACE_PEEKDATA.ptrace一次只能读取一个单词,因此读取目标进程的大堆需要太多的调用.这非常非常慢.
该工具基于特定JVM版本的知识重建JVM内部结构.由于不同版本的JVM具有不同的内存布局,因此-F只有jmap来自与目标Java进程相同的JDK 才能使用模式.
该工具创建堆转储本身,然后恢复目标进程.
优点.
ptrace只要操作系统级权限足够,它就可以运行 例如,root可以转储所有其他用户的进程.缺点.
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]
就像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)
它也可以与其他命令一起使用,例如jcmd和jinfo。