我必须运行 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 ...
- 使用
-F
可以进行堆转储吗? - 我等了 20 分钟,还没有完成。任何想法为什么?
原文由 rayman 发布,翻译遵循 CC BY-SA 4.0 许可协议
jmap
vs.jmap -F
, as well asjstack
vs.jstack -F
use completely different mechanisms to communcate with the target JVM.jmap / jstack
在没有
-F
的情况下运行时,这些工具使用 Dynamic Attach Mechanism 。这工作如下。在连接到Java进程1234之前,
jmap
创建一个文件.attach_pid1234
/tmp
。然后
jmap
发送SIGQUIT
到目标进程。当 JVM 捕捉到信号并找到.attach_pid1234
时,它会启动AttachListener
线程。AttachListener
线程创建 UNIX 域套接字/tmp/.java_pid1234
监听来自外部工具的命令。出于安全原因,当接受连接(来自
jmap
)时,JVM 会验证套接字对等方的凭据是否等于 JVM 进程的euid
和egid
。这就是为什么jmap
如果由不同的用户(甚至是 root)运行将不起作用。jmap
连接到socket,并发送dumpheap
命令。该命令由JVM的
AttachListener
线程读取并执行。所有输出都被发送回套接字。由于堆转储是由 JVM 直接在进程内进行的,因此操作非常快。但是,JVM 只能在安全点执行此 操作。如果无法到达安全点(例如进程挂起、无响应或长时间 GC 正在进行),jmap
将超时并失败。让我们总结一下动态附加的优点和缺点。
优点。
jmap
或jstack
连接到任何其他版本的 JVM。缺点。
euid
/egid
)运行。-XX:+DisableAttachMechanism
启动,则将无法工作。jmap -F / jstack -F
当使用
-F
运行时,工具会切换到具有 HotSpot Serviceability Agent 的特殊模式。在这种模式下,目标进程被冻结;这些工具通过操作系统调试工具读取其内存,即 Linux 上的ptrace
。jmap -F
PTRACE_ATTACH
。目标进程响应SIGSTOP
信号无条件挂起。该工具使用
PTRACE_PEEKDATA
读取 JVM 内存。ptrace
一次只能读取一个字,所以读取目标进程的大堆需要调用太多。这是非常非常缓慢的。该工具基于特定 JVM 版本的知识重构 JVM 内部结构。由于不同版本的 JVM 有不同的内存布局,
-F
模式只有在jmap
来自与目标 Java 进程相同的 JDK 时才有效。该工具自己创建堆转储,然后恢复目标进程。
优点。
ptrace
只要操作系统级别的权限足够,就可以工作。例如root
可以转储所有其他用户的进程。缺点。
jmap
尝试处理所有特殊情况,但有时可能会发生目标 JVM 处于不一致状态的情况。笔记
有一种更快的方法可以在强制模式下进行堆转储。首先,使用
gcore
创建一个 coredump,然后在生成的核心文件上运行jmap
。请参阅 相关问题。