jvm attach api

文章目录

  • 1. 简介
  • 2.主要接口与类
    • 2.1 class VirtualMachine
      • 2.1.1 概述
      • 2.1.2 方法
      • 2.1.3 使用示例
    • 2.2 Class AttachPermission
  • 3. attach 实现
    • 3.1 外部进程
    • 3.2 目标VM

1. 简介

关于Attach API:
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.

这是Sun私有实现(即不是Jvm标准规范,其他虚拟机不一定有这个能力)。该api的功能是让外部进程可以 在目标JVM(运行被监控、被控制的程序的JVM) 中启动一个线程,该线程会加载运行Agent,然后线程会将本jvm的状态返回给外部进程。

2.主要接口与类

2.1 class VirtualMachine

2.1.1 概述

public abstract class VirtualMachine
extends Object

该类表示将要被“附着的”Java虚拟机,也被称为目标虚拟机(target virtual machine,target vm)。 外部进程(通常来说是外部的监控工具、或是管理控制台,如jconsole,jprofile) 使用该类实例来 将agent 加载到目标虚拟机中。 例如,使用Java编写的profiler工具就会使用VirtaulMachine类实例来加载profiler agent到被监控的jvm中。

通过VirtualMachine的类静态方法attach(string id)来获取代表target vm的VirtaulMachine实例。该方法 id参数一般是arget vm的进程Pid。

另外,也可以 通过 类静态方法 attach(VirtualMachineDescriptor vmd) 来获取一个VirtaulMachine实例( 可以使用静态方法VirtualMachine.list()方法获取一个VirtualMachineDescriptor 列表 )。

当获取到VirtualMachine对象实例后,就可以调用loadAgent,loadAgentLibrary,loadAgentPath方法操作target VM了。

这几个方法的区别:

  1. loadAgent方法用于加载 用Java写的、打包成jar的agent;
  2. loadAgentLibrary 和loadAgentPath 是用于加载基于JVM TI接口的 打包成动态库形式的agent。

2.1.2 方法

描述符 方法签名 描述
protected VirtualMachine(AttachProvider provider, String id) (构造函数,私有) Initializes a new instance of this class.
static VirtualMachine attach(String id) Attaches to a Java virtual machine.
static VirtualMachine attach(VirtualMachineDescriptor vmd) Attaches to a Java virtual machine.
abstract void detach() Detach from the virtual machine.
abstract Properties getAgentProperties() Returns the current agent properties in the target virtual machine.
abstract Properties getSystemProperties() Returns the current system properties in the target virtual machine.
String id() Returns the identifier for this Java virtual machine.
static List list() Return a list of Java virtual machines.
void loadAgent(String agent) Loads an agent.
abstract void loadAgent(String agent, String options) Loads an agent.
void loadAgentLibrary(String agentLibrary) Loads an agent library.
abstract void loadAgentLibrary(String agentLibrary, String options) Loads an agent library.
void loadAgentPath(String agentPath)
abstract void loadAgentPath(String agentPath, String options) Load a native agent library by full pathname.
AttachProvider provider() Returns the provider that created this virtual machine.
String toString() Returns the string representation of the VirtualMachine.
int hashCode() Returns a hash-code value for this VirtualMachine.
boolean equals(Object ob) Tests this VirtualMachine for equality with another object.

2.1.3 使用示例

        // attach to target VM
        VirtualMachine vm = VirtualMachine.attach("2177");

        // get system properties in target VM
        Properties props = vm.getSystemProperties();

        // construct path to management agent
        String home = props.getProperty("java.home");
        String agent = home + File.separator + "lib" + File.separator 
            + "management-agent.jar";

        // load agent into target VM
        vm.loadAgent(agent, "com.sun.management.jmxremote.port=5000");

        // detach
        vm.detach();

2.2 Class AttachPermission

public final class AttachPermission
extends BasicPermission

当设置了 SecurityManager后,在外部程序调用VirtalMachine.attach时,target VM会检查外部程序的权限。

当创建AttachProvider时,会也检查你的权限。

AttachPermission对象包含一个名字(目前不知道操作列表这种细化的权限)。

对象构造:

  1. public AttachPermission(String name):创建一个AttachPermission 对象,name参数只能是“attachVirtualMachine” 或“createAttachProvider”;
  2. public AttachPermission(String name, String actions): 创建一个AttachPermission 对象,name参数只能是“attachVirtualMachine” 或“createAttachProvider”;actions未被使用,应该传入null或是空字符串。

attachVirtualMachine 与createAttachProvider 的区别:
jvm attach api_第1张图片

3. attach 实现

参考:http://ifeve.com/jvm-attach/

3.1 外部进程

在Linux下,attach时,外部进程会在目标进程的cwd目录下创建文件:/proc//cwd/.attach_pid。 然后等待给JVM下的所有线程发送SIGQUIT信号,再作轮询等待看目标进程是否创建了某个文件,attachTimeout默认超时时间是5000ms,可通过设置系统变量sun.tools.attach.attachTimeout来指定。

3.2 目标VM

JVM在启动时,会创建“Signal Dispatcher”线程。当外部进程给所有子进程发送SIGQUIT信号,而JVM将信号就传给了“Signal Dispatcher”(其他线程对该信号进行了屏蔽)。

对于Signal Dispatcher线程: 当信号是SIGBREAK(在jvm里做了#define,其实就是SIGQUIT)的时候,就会触发AttachListener::is_init_trigger()的执行,创建出AttachListener线程。

AttachListener线程:AttachListener线程创建了一个监听套接字,并创建了一个文件/tmp/.java_pid,这个文件就是外部进程之前一直在轮询等待的文件,随着这个文件的生成,意味着attach的过程圆满结束了。

attach listener接收请求
该线程不断从队列中取AttachOperation,然后找到请求命令对应的方法进行执行。比如jstack的 thread dump命令命令,attach listener找到 { “threaddump”, thread_dump }的映射关系,然后执行thread_dump方法

你可能感兴趣的:(JAVA)