Java Attach机制
2020-04-03 本文已影响0人
万福来
Java Attach机制
在JVM运行时,我们经常需要获取目标JVM运行时的相关信息。最典型的一个场景就是通过jstack命令输出当前的线程dump。
对于这种场景,java提供了attach机制。通过attach机制,我们可以直接attach到目标JVM进程,然后进行一些操作,比如获取内存dump、线程dump,类信息统计(比如已加载的类以及实例个数等),动态加载agent,动态设置vm flag(但是并不是所有的flag都可以设置的,因为有些flag是在jvm启动过程中使用的,是一次性的),打印vm flag,获取系统属性等。
Attach实现原理
attach机制的实现涉及到了进程间的通信。那么Attach机制是如何让两个JVM进程之间可以正常通信呢?经常通过jstack查看线程dump的同学可能会留意到下面这个两个线程:
"Attach Listener" #10 daemon prio=9 os_prio=31 tid=0x00007fef2283a000 nid=0x4b03 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007fef22030000 nid=0x3907 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
这两个线程都是JVM线程。其中每个JVM都会有Signal Dispatcher线程,用于处理信号。Attach Listener线程用于JVM进程间的通信,但是它不一定会启动,启动它有两种方式。
Attach Listener启动方式
- java程序启动的时候通过jvm参数指定启动该线程;增加 -XX:+StartAttachListener;
- attach目标JVM成功后,目标JVM启动该线程。如果程序启动时没有启动该线程,则依靠Signal Dispatcher线程收到attach信号后启动线程。
- Attach Listener线程启动后创建一个监听套接字,并创建一个socketFile,客户端和目标JVM进程就通过这个socketFile进行通信,客户端发送相关命令到socketFile,Attach Listener监听这个socketFile,发下有请求命令,就直接解析,然后调用命令对应的方法,最后返回结果给客户端。