VirtualMachine

attach and detach

package sample;

import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;

import java.io.IOException;

public class VMAttach {
    public static void main(String[] args) throws IOException, AttachNotSupportedException {
        // 注意:需要修改 pid 的值
        String pid = "1234";
        VirtualMachine vm = VirtualMachine.attach(pid);
        vm.detach();
    }
}

loadAgent

import java.lang.instrument.Instrumentation;

public class DynamicAgent {
    public static void agentmain(String agentArgs, Instrumentation inst) {
        Class<?> agentClass = DynamicAgent.class;
        System.out.println("Agent-Class: " + agentClass.getName());
        System.out.println("agentArgs: " + agentArgs);
        System.out.println("Instrumentation: " + inst.getClass().getName());
        System.out.println("ClassLoader: " + agentClass.getClassLoader());
        System.out.println("Thread Id: " + Thread.currentThread().getName() + "@" +
                Thread.currentThread().getId() + "(" + Thread.currentThread().isDaemon() + ")"
        );
        System.out.println("Can-Redefine-Classes: " + inst.isRedefineClassesSupported());
        System.out.println("Can-Retransform-Classes: " + inst.isRetransformClassesSupported());
        System.out.println("Can-Set-Native-Method-Prefix: " + inst.isNativeMethodPrefixSupported());
        System.out.println("========= ========= =========");
    }
}
package sample;

import com.sun.tools.attach.AgentInitializationException;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;

import java.io.IOException;

public class VMAttach {
    public static void main(String[] args) throws IOException, AttachNotSupportedException,
            AgentLoadException, AgentInitializationException {
        // 注意:需要修改 pid 的值
        String pid = "1234";
        String agentPath = "D:\\git-repo\\learn-java-agent\\target\\TheAgent.jar";
        VirtualMachine vm = VirtualMachine.attach(pid);
        vm.loadAgent(agentPath, "Hello JVM Attach");
        vm.detach();
    }
}

getSystemProperties

package sample;

import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;

import java.io.IOException;
import java.util.Properties;

public class VMAttach {
    public static void main(String[] args) throws IOException, AttachNotSupportedException {
        // 注意:需要修改 pid 的值
        String pid = "1234";
        VirtualMachine vm = VirtualMachine.attach(pid);
        Properties properties = vm.getSystemProperties();
        properties.list(System.out);
        vm.detach();
    }
}

Output:

-- listing properties --
java.runtime.name=Java(TM) SE Runtime Environment
sun.boot.library.path=C:\Program Files\Java\jdk1.8.0_301\jr...
java.vm.version=25.301-b09
java.vm.vendor=Oracle Corporation
java.vendor.url=http://java.oracle.com/
path.separator=;
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
...

getAgentProperties

package sample;

import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;

import java.io.IOException;
import java.util.Properties;

public class VMAttach {
    public static void main(String[] args) throws IOException, AttachNotSupportedException {
        // 注意:需要修改 pid 的值
        String pid = "1234";
        VirtualMachine vm = VirtualMachine.attach(pid);
        Properties properties = vm.getAgentProperties();
        properties.list(System.out);
        vm.detach();
    }
}

Output:

-- listing properties --
sun.jvm.args=-javaagent:C:\Program Files\JetBrains...
sun.jvm.flags=
sun.java.command=sample.Program

list

import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
import com.sun.tools.attach.spi.AttachProvider;

import java.io.IOException;
import java.util.List;

public class VMAttach {
    public static void main(String[] args) throws IOException, AttachNotSupportedException {
        List<VirtualMachineDescriptor> list = VirtualMachine.list();

        for (VirtualMachineDescriptor vmd : list) {
            String id = vmd.id();
            String displayName = vmd.displayName();
            AttachProvider provider = vmd.provider();
            System.out.println("Id: " + id);
            System.out.println("Name: " + displayName);
            System.out.println("Provider: " + provider);
            System.out.println("=====================");
        }
    }
}
package sample;

import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;

import java.io.IOException;
import java.util.List;
import java.util.Properties;

public class VMAttach {
    public static void main(String[] args) throws IOException, AttachNotSupportedException {
        List<VirtualMachineDescriptor> list = VirtualMachine.list();

        String className = "sample.Program";
        VirtualMachine vm = null;
        for (VirtualMachineDescriptor item : list) {
            String displayName = item.displayName();
            if (displayName != null && displayName.equals(className)) {
                vm = VirtualMachine.attach(item);
                break;
            }
        }

        if (vm != null) {
            Properties properties = vm.getSystemProperties();
            properties.list(System.out);
            vm.detach();
        }
    }
}

AttachProvider

import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.spi.AttachProvider;

public class VMAttach {
    public static void main(String[] args) throws Exception {
        // 注意:需要修改 pid 的值
        String pid = "1234";
        VirtualMachine vm = VirtualMachine.attach(pid);
        AttachProvider provider = vm.provider();
        String name = provider.name();
        String type = provider.type();
        System.out.println("Provider Name: " + name);
        System.out.println("Provider Type: " + type);
        System.out.println("Provider Impl: " + provider.getClass());
    }
}

Windows 7 环境下输出:

Provider Name: sun
Provider Type: windows
Provider Impl: class sun.tools.attach.WindowsAttachProvider

Ubuntu 20 环境下输出:

Provider Name: sun
Provider Type: socket
Provider Impl: class sun.tools.attach.LinuxAttachProvider

总结

本文主要是对 Attach API 的内容进行举例。