JVM的動態agent機制:在main函式啟動之後執行agent
premain是Java SE5開始就提供的代理方式,由於其必須在命令列指定代理jar,並且代理類必須在main方法前啟動。因此,要求開發者在應用前就必須確認代理的處理邏輯和引數內容等等。在有些場合下,premain代理方式不能滿足需求。為解決執行時啟動代理類的問題,Java SE6開始提供了在應用程式的VM啟動後在動態新增代理的方式,即agentmain方式。
與Permain類似,agent方式同樣需要提供一個agent jar,並且這個jar需要滿足:
1、在manifest中指定Agent-Class屬性,值為代理類全路徑
2、代理類需要提供public static void agentmain(String args, Instrumentation inst)或public static void agentmain(String args)方法。並且再二者同時存在時以前者優先。args和inst和premain中的一致
package aty.agent.after; import java.lang.instrument.Instrumentation; public class AgentAfterMain { public static void agentmain(String args, Instrumentation inst) { System.out.println("loadagent after main run.args=" + args); Class<?>[] classes = inst.getAllLoadedClasses(); for (Class<?> cls : classes) { System.out.println(cls.getName()); } System.out.println("agent run completely."); } }
將該代理類打成jar包,並修改MANIFEST.MF檔案
Manifest-Version: 1.0
Agent-Class: aty.agent.after.AgentAfterMain
編寫好agent jar之後,接下來需要將該jar掛接到目標程序的jvm中執行。由於agent main方式無法向pre main方式那樣在命令列指定代理jar,因此需要藉助Attach Tools API。使用com.sun.tools.attach包下的VirtualMachine類,使用attach pid 來得到相應的VirtumalMachine,使用loadAgent 方法指定AgentMain所在類並載入。其中com.sun.tools.attach.VirtualMachine的jar包是jdk下lib中的tools.jar
package aty.agent.after;
import com.sun.tools.attach.VirtualMachine;
public class RunAttach
{
public static void main(String[] args) throws Exception
{
// args[0]傳入的是某個jvm程序的pid
String targetPid = args[0];
VirtualMachine vm = VirtualMachine.attach(targetPid);
vm.loadAgent("F:/workspaces/j2se練習程式碼/jvm_high_api/agentmain.jar",
"toagent");
}
}