# 3.1 Attach API 简介

从JDK1.6开始可以使用Attach API连接到目标JVM上并让目标JVM加载一个Java Agent。 Attach API的包名称为com.sun.tools.attach。如下图3-1所示主要包含2个类:VirtualMachine和VirtualMachineDescriptor。

图3-1 Attach API 官方文档

图3-1 Attach API 官方文档

VirtualMachine代表一个Java虚拟机,也就是监控的目标虚拟机,而VirtualMachineDescriptor用来描述虚拟机信息,配合VirtualMachine类完成各种功能。

主要的功能实现在VirtualMachine以及子类中,其它类起到辅助作用。下面的代码使用Attach API连接到进程pid为72695的JVM进程上,然后读取目标JVM的系统参数并输出到终端,最后调用detach方法与目标JVM断开连接。

import java.util.Properties;

import com.sun.tools.attach.VirtualMachine;

public class Main {

    public static void main(String[] args) throws Exception {
        // attach to target VM
        VirtualMachine vm = VirtualMachine.attach("72695");

        // read target vm system properties
        Properties properties = vm.getSystemProperties();
        for (Object key : properties.keySet()) {
            System.out.println(key + "=" + properties.getProperty(key.toString()));
        }

        // detach
        vm.detach();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

上面代码输出目标JVM的系统属性参数,其结果如下所示。

java.runtime.name=Java(TM) SE Runtime Environment
java.protocol.handler.pkgs=org.springframework.boot.loader
java.vm.version=25.261-b12
gopherProxySet=false
java.vm.vendor=Oracle Corporation
// ... 其他参数省略
1
2
3
4
5
6

上面代码第9行处,可以直观的理解在调用attach方法之后,就获得了一个目标JVM的VirtualMachine对象,调用VirtualMachine对象的方法(第12行处调用getSystemProperties方法)就可以完成对目标JVM的操作。除了获取目标 JVM 系统参数的方法之外,VirtualMachine还有如下方法,如下所示。

// 列出当前主机上的所有JVM
public static List<VirtualMachineDescriptor> list()

// 执行attach/detach
public static VirtualMachine attach(VirtualMachineDescriptor vmd)
public abstract void detach() throws IOException

// 加载Agent
public abstract void loadAgentLibrary(String agentLibrary, String options)
public void loadAgentLibrary(String agentLibrary)
public abstract void loadAgentPath(String agentPath, String options)
public void loadAgentPath(String agentPath)
public abstract void loadAgent(String agent, String options)
public void loadAgent(String agent)

// 获取JVM系统参数
public abstract Properties getSystemProperties() throws IOException
public abstract Properties getAgentProperties() throws IOException

// 在目标虚拟机中启动JMX管理代理
public abstract void startManagementAgent(Properties agentProperties) throws IOException
public abstract String startLocalManagementAgent() throws IOException;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22