一、agent分类

  • 一种是在主程序之前运行的Agent
  • 一种是在主程序之后运行的Agent(前者的升级版,1.6以后提供)

二、javaagent概述

javaagent(Java代理程序)是java命令的一个参数。参数 javaagent 可以用于指定一个 jar 包,并且对该 java 包有2个要求:

(1)这个 jar 包的 MANIFEST.MF 文件必须指定 Premain-Class 项
(2)Premain-Class 指定的那个类必须实现 premain() 方法。premain() 方法,从字面上理解,就是运行在 main 函数之前的方法。当Java 虚拟机启动时,在执行 main 函数之前,JVM 会先运行 -javaagent 所指定 jar 包内 Premain-Class 类的 premain 方法

java命令的参数介绍:

  • -agentlib:[=<选项>] 加载本机代理库 , 例如 -agentlib:hprof
    另请参阅 -agentlib:jdwp=help 和 -agentlib:hprof=help
  • -agentpath:[=<选项>]
    按完整路径名加载本机代理库
  • -javaagent:[=<选项>]
    加载 Java 编程语言代理, 请参阅 java.lang.instrument

在上面-javaagent参数中提到了参阅java.lang.instrument,这是在rt.jar 中定义的一个包,该路径下有两个重要的类:

javaagent 指定 -javaagent命令_java

三、主程序之后运行的agent

在 Java SE 6 的 Instrumentation 当中,提供了一个新的代理操作方法:agentmain,可以在 main 函数开始运行之后再运行。跟premain函数一样, 开发者可以编写一个含有agentmain函数的 Java 类

//采用attach机制,被代理的目标程序VM有可能很早之前已经启动,当然其所有类已经被加载完成,这个时候需要借助Instrumentation#retransformClasses(Class<?>... classes)让对应的类可以重新转换,从而激活重新转换的类执行ClassFileTransformer列表中的回调
public static void agentmain (String agentArgs, Instrumentation inst)

public static void agentmain (String agentArgs)

同样,agentmain 方法中带Instrumentation参数的方法比不带该参数的方法优先级更高。开发者必须在 manifest 文件里面设置“Agent-Class”来指定包含 agentmain 函数的类

Java6以后实现启动后加载的新实现是Attach API。Attach API 很简单,只有 2 个主要的类,都在 com.sun.tools.attach 包里面

javaagent 指定 -javaagent命令_Java_02

  • VirtualMachine 字面意义表示一个Java 虚拟机,也就是程序需要监控的目标虚拟机,提供了获取系统信息(比如获取内存dump、线程dump,类信息统计(比如已加载的类以及实例个数等), loadAgent,Attach 和 Detach (Attach 动作的相反行为,从 JVM 上面解除一个代理)等方法,可以实现的功能可以说非常之强大 。该类允许我们通过给attach方法传入一个jvm的pid(进程id),远程连接到jvm上 。代理类注入操作只是它众多功能中的一个,通过loadAgent方法向jvm注册一个代理程序agent,在该agent的代理程序中会得到一个Instrumentation实例,该实例可以 在class加载前改变class的字节码,也可以在class加载后重新加载。在调用Instrumentation实例的方法时,这些方法会使用ClassFileTransformer接口中提供的方法进行处理
  • VirtualMachineDescriptor 则是一个描述虚拟机的容器类,配合 VirtualMachine 类完成各种功能。

    既然是两个进程之间通信,那肯定得建立起连接,VirtualMachine.attach动作类似TCP创建连接的三次握手,目的就是搭建attach通信的连接。而后面执行的操作,例如vm.loadAgent,其实就是向这个socket写入数据流,接收方target VM会针对不同的传入数据来做不同的处理

四、javaagent用途

用来协助监测、运行甚至替换其他JVM上的程序。使用它可以实现虚拟机级别的 AOP(能够实现字节码增强) 功能