从JDK6开始引入,除了Solaris平台的Sun JVM支持远程的Attach,在其他平台都只允许Attach到本地的JVM上
-
什么是attach机制?
说简单点就是jvm提供一种jvm进程间通信的能力,能让一个进程传命令给另外一个进程,并让它执行内部的一些操作,比如说我们为了让另外一个jvm进程把线程dump出来,那么我们跑了一个jstack的进程,然后传了个pid的参数,告诉它要哪个进程进行线程dump,既然是两个进程,那肯定涉及到进程间通信,以及传输协议的定义,比如要执行什么操作,传了什么参数等
-
进程dump出来的�信息中会包含两个线程
2014-06-18 12:56:14 Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.51-b03 mixed mode): "Attach Listener" daemon prio=5 tid=0x00007fb0c6800800 nid=0x440b waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Signal Dispatcher" daemon prio=5 tid=0x00007fb0c4815800 nid=0x4d03 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE .........
- Attach Listener(在jvm起来的时候可能并没有)
- Signal Dispatcher(随jvm启动而启动)
-
UNIX-进程间通信(IPC: 这里只是简述,�细节见stevens的书)
- 1.消息传递(管道,FIFO,Posix,System V消息队列)
- 2.同步(互斥锁,条件变量,读写锁,文件和记录锁,Posix和System V信号量)
- 3.共享内存区(匿名共享内存区,有名Posix�共享内存区,有名System V共享内存区)
- 4.过程调用(Solaris门,Sun RPC)
- 消息队列和过程调用往往单独使用,它们通常提供了自己的同步机制
- 共享内存区通常由应用程序提供同步
- 如何选用哪种IPC?
- 考虑的前提
- 1.是否联网 联网用socket代替IPC
- 2.可移植性(上面讨论的那么多技术不是所有系统都支持的)
- 3.性能(对上面技术都测试一遍)
- 4.实时调度
- 各种IPC的特性及局限,请参考stevens书-后记
- 考虑的前提
- 性能比较(这里是书上的例子测试的,生产时建议模拟生产写例子测试)
- 测量尺度 - 带宽和延迟
- Unix域套接字
-
unix domain socket
- 基于socket的框架上发展出一种IPC机制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC 更有效率 :
- 不需要经过网络协议栈
- 不需要打包拆包、计算校验和、维护序号和应答等
- 只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。UNIX Domain Socket也提供面向流和面向数据包两种API接口,类似于TCP和UDP,但是面向消息的UNIX Domain Socket也是可靠的,消息既不会丢失也不会顺序错乱。
- 应用
- UNIX Domain Socket是全双工的,API接口语义丰富,相比其它IPC机制有明显的优越性,目前已成为使用最广泛的IPC机制,比如X Window服务器和GUI程序之间就是通过UNIX Domain Socket通讯的。
- Nginx通过unix:/socket与fastcgi连接,提升性能,比tcp socket要高效
- 用Unix domain socket写的Demo
- 使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创建一个socket文件描述符,address family指定为AF_UNIX,type可以选择SOCK_DGRAM或SOCK_STREAM,protocol参数仍然指定为0即可。通常是指定/tmp/目录下的一个文件作为通信路径
- 基于socket的框架上发展出一种IPC机制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC 更有效率 :
-
external process跟target VM process间的IPC问题
On Linux and Solaris, the client creates a file named .attach_pid<pid> and sends a SIGQUIT to the target JVM process. The existence of this file causes the SIGQUIT handler in HotSpot to start the attach listener thread. On Windows, the client uses the Win32 CreateRemoteThread function to create a new thread in the target process. The attach listener thread then communicates with the source JVM in an OS dependent manner:
On Solaris, the Doors IPC mechanism is used. The door is attached to a file in the file system so that clients can access it.
On Linux, a Unix domain socket is used. This socket is bound to a file in the filesystem so that clients can access it.
On Windows, the created thread is given the name of a pipe which is served by the client. The result of the operations are written to this pipe by the target JVM.- 以Linux平台为栗,使用了两种IPC方式
- 信号机制。首先external process会先发送一个SIGQUIT信号给target VM process,target VM会创建一个Attach Listener线程;
- Unix domain socket。然后Attach Listener线程会通过Unix domain socket与external process建立连接,之后就可以基于这个socket进行通信了。
- 这个过程中,会有两个文件被创建
- .attach_pid<pid>,external process会创建这个文件,为的是触发Attach Listener线程的创建,因为SIGQUIT信号不是只有external process才会发的,通过这个文件来告诉target VM,有attach请求过来了。相关代码在LinuxVirtualMachine.java中;
- .java_pid<pid>,target VM会创建这个文件,这个是因为Unix domain socket本身的实现机制需要去创建一个文件,通过这个文件来进行IPC。相关代码在attachListener_linux.cpp中;
- 以Linux平台为栗,使用了两种IPC方式
-
Attach机制用途
- 内存dump
- 线程dump
- 类信息统计(比如加载的类及大小以及实例个数等)
- 动态加载agent(使用过btrace的应该不陌生)
- 动态设置vm flag(但是并不是所有的flag都可以设置的,因为有些flag是在jvm启动过程中使用的,是一次性的)
- 打印vm flag
- 获取系统属性等
-
-
官方解释
The Attach API is a Sun Microsystems extension that provides a mechanism to attach to a Java™ virtual machine. A tool written in the Java Language, uses this API to attach to a target virtual machine and load its tool agent into that virtual machine. For example, a management console might have a management agent which it uses to obtain management information from instrumented objects in a virtual machine. If the management console is required to manage an application that is running in a virtual machine that does not include the management agent, then this API can be used to attach to the target virtual machine and load the agent.
另一个解释
This is a Sun private mechanism that allows an external process to start a thread in HotSpot that can then be used to launch an agent to run in that HotSpot, and to send information about the state of HotSpot back to the external process.
-
-
Attach API Example
-
com.sun.tools.attach.VirtualMachine
- attach
- loadAgentXXX
- detach
-
AttachProvider
- AttachProvider来提供不同的Attach方式,当然这不是一件简单的事情,因为实际上是需要JVM支持的。以Windows平台为例,实现了WindowsAttachProvider
-
1.JConsole连接界面中的本地部分就是通过这个API来做的
List<VirtualMachineDescriptor> list = VirtualMachine.list(); for (VirtualMachineDescriptor vmd : list) { System.out.println("pid:" + vmd.id() + ":" + vmd.displayName()); }
-
2.Attach到特定进程的JVM上,并加载Agent,我们看看jconsole是怎么做的(见sun.tools.jconsole. LocalVirtualMachine)
VirtualMachine virtualmachine = VirtualMachine.attach(pid); String javaHome = virtualmachine.getSystemProperties().getProperty("java.home"); String agentPath = javaHome + File.separator + "jre" + File.separator + "lib" + File.separator + "management-agent.jar"); File file = new File(agentPath); if(!file.exists()) { agentPath = javaHome + File.separator + "lib" + File.separator + "management-agent.jar"; file = new File(agentPath); if(!file.exists()){ throw new IOException("Management agent not found"); } } agentPath = file.getCanonicalPath(); try{ virtualmachine.loadAgent(agentPath, "com.sun.management.jmxremote"); } Properties properties = virtualmachine.getAgentProperties(); address = (String)properties.get("com.sun.management.jmxremote.localConnectorAddress"); virtualmachine.detach();
-
-
JVM如何实现attach机制
- 请阅读笨神的文章: JVM Attach机制实现