运行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 ...
- 使用
-F
适合堆取出堆? - 我等了20分钟,还没有完成。 任何想法为什么?
jmap
与jmap -F
以及jstack
与jstack -F
使用完全不同的机制来与目标JVM进行通信。
jmap / jstack
当运行没有-F
这些工具使用dynamic连接机制 。 这工作如下。
-
在连接到Java进程1234之前,
jmap
在目标进程的工作目录或/tmp
创build一个.attach_pid1234
的文件。 -
然后
jmap
将SIGQUIT
发送到目标进程。 当JVM捕获信号并find.attach_pid1234
,它启动AttachListener
线程。 -
AttachListener
线程创buildUNIX域套接字/tmp/.java_pid1234
以侦听来自外部工具的命令。 -
出于安全原因,当接受来自
jmap
的连接时,JVM将validation对等端的凭证是否等于JVM进程的euid
和egid
。 这就是为什么如果由不同的用户(即使是root)运行jmap
也不行。 -
jmap
连接到套接字,并发送dumpheap
命令。 -
该命令由JVM的
AttachListener
线程读取并执行。 所有的输出都被发送回套接字。 由于堆转储是由JVM直接进行的,操作非常快。 但是,JVM只能在安全点上执行此操作 。 如果无法达到安全点(例如进程挂起,没有响应或长时间的GC正在进行),则jmap
将超时并失败。
我们来总结dynamic连接的优点和缺点。
优点。
- 堆转储和其他操作由JVM以最高速度协同运行。
- 您可以使用任何版本的
jmap
或jstack
连接到任何其他版本的JVM。
缺点。
- 该工具应该由与目标JVM相同的用户(
euid
/egid
)运行。 - 只能在实时和健康的JVM上使用。
- 如果目标JVM以
-XX:+DisableAttachMechanism
启动,将无法工作。
jmap -F / jstack -F
当使用-F
运行时,工具切换到以HotSpot可维护性代理程序为特色的特殊模式。 在这种模式下,目标进程被冻结; 这些工具通过OSdebugging工具读取它的内存,也就是Linux上的ptrace
。
-
jmap -F
在目标JVM上调用PTRACE_ATTACH
。 响应于SIGSTOP
信号,目标进程被无条件地暂停。 -
该工具使用
PTRACE_PEEKDATA
读取JVM内存。ptrace
只能读取一个字,所以读取目标进程的大堆时需要太多的调用。 这是非常非常缓慢的。 -
该工具基于特定JVM版本的知识重buildJVM内部结构。 由于不同版本的JVM具有不同的内存布局,因此
-F
模式仅在jmap
来自与目标Java进程相同的JDK时才起作用。 -
该工具自己创build堆转储,然后恢复目标进程。
优点。
- 目标JVM不需要合作。 甚至可以在挂起的过程中使用。
- 只要操作系统级别的权限足够,
ptrace
可以工作。 例如root
可以转储所有其他用户的进程。
缺点。
- 非常缓慢的大堆。
- 该工具和目标进程应该来自相同版本的JDK。
- 工具在强制模式下连接时,不保证安全点。 尽pipe
jmap
尝试处理所有特殊情况,但有时可能发生目标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>
它也可以和其他命令一起使用,比如jcmd
和jinfo
。