Java Attach API

catalog

1. instrucment與Attach API
2. BTrace: VM Attach的兩種方式
3. Sun JVM Attach API

?

1. instrucment與Attach API

JDK5中增加了一個包java.lang.instrucment,能夠對JVM底層組件進行訪問。在JDK 5中,Instrument 要求在運行前利用命令行參數或者系統參數來設置代理類,在實際的運行之中,虛擬機在初始化之時(在絕大多數的 Java 類庫被載入之前),instrumentation的設置已經啟動,并在虛擬機中設置了回調函數,檢測特定類的加載情況,并完成實際工作
?在Java5中,開發基于Instrucment的應用,需要以下幾個步驟

1. 編寫premain函數
?2. jar文件打包
?3. 運行agent 

但是在實際的很多的情況下,我們沒有辦法在虛擬機啟動之時就為其設定代理,這樣實際上限制了instrument的應用。而Java SE 6的新特性改變了這種情況,通過Java Tool API中的attach方式,我們可以很方便地在運行過程中動態地設置加載代理類,以達到instrumentation的目的
?在JDK6中,針對這點做了改進,開發者可以在main開始執行以后,再開啟自己的Instrucment程序
Attach API不是Java的標準API,而是Sun公司提供的一套擴展API,用來向目標JVM"附著"(Attach)代理工具程序的。有了它,開發者可以方便的監控一個JVM,運行一個外加的代理程序,Sun JVM Attach API功能上非常簡單,僅提供了如下幾個功能

1. 列出當前所有的JVM實例描述
2. Attach到其中一個JVM上,建立通信管道
3. 讓目標JVM加載Agent

Relevant Link:

http://iamzhongyong.iteye.com/blog/1843558

?

2. BTrace: VM Attach的兩種方式

BTrace的特點之一就是可以動態Attach到一個運行的JVM進程上,然后根據BTrace腳本來對目標JVM進行相應的操作
JVM的 Attach有兩種方式

1. 指定javaagent參數
2. 運行時動態attach

0x1: 指定javaagent參數

這種方式的特點就是在目標JVM啟動時,就確定好了要加載什么樣的代理對象,例如

java -javaagent:xxxx.jar TestMain

TestMain.java

package test;public class TestMain 
{ public static void main(String[] args) throws InterruptedException{System.out.println("Hello");}}

TestAgent.java

package test;import java.lang.instrument.Instrumentation;
import java.io.*;public class TestMain 
{ public static void agentmain(String args, Instrumentation inst) throws Exception {System.out.println("Args:" + args);}public static void premain(String args, Instrumentation inst) throws Exception {System.out.println("Pre Args:" + args);Class[] classes = inst.getAllLoadedClasses();for (Class clazz : classes) {System.out.println(clazz.getName());}} 
}

TestAgent類比較簡單,最終它會在目標類的Main方法執行之前,執行premain方法,其主要動作是將以及加載的類打印出來。 我們需要將這個類打包成jar文件,以便在目標JVM啟動時候,以參數形式指定給它。打成jar的同時,設定MANIFEST.MF文件的內容。告知目標JVM該如何處理

Agent-Class: TestAgent
Premain-Class: TestAgent
Can-Redine-Classes: true
Can-Retransform-Classes: true

用jar命令將TestAgent打包

1. 編譯TestAgent
javac TestAgent.java2. jar打包
jar cvmf MANIFEST.MF xxx.jar TestAgent.class

啟動TestMain,并設置javaagent參數

1. 編譯TestMain
javac TestMain.java 2. 啟動TestMain
java -javaagent:xxx.jar TestMain

0x2: 動態Attach,load指定Agent

這種方式與之前指定參數的不同在于,其可以在JVM已經運行的情況下,動態的附著上去,并可以動態加載agent
TestMain.java

public class TestMain 
{public static void main(String[] args) throws InterruptedException {  while(true){  Thread.sleep(10000);  new Thread(new WaitThread()).start();  }  }  static class WaitThread implements Runnable {  @Override  public void run() {  System.out.println("Hello"); }       }  
}

TestAgent.java

import java.lang.instrument.Instrumentation;
import java.io.*;public class TestAgent
{ public static void agentmain(String args, Instrumentation inst) throws Exception {System.out.println("Args:" + args);}public static void premain(String args, Instrumentation inst) throws Exception {System.out.println("Pre Args:" + args);Class[] classes = inst.getAllLoadedClasses();for (Class clazz : classes) {System.out.println(clazz.getName());}} 
}

動態加載agent的情況下,被調用的是agentmain方法, 其會在JVMload的時候,被調用
MANIFEST.MF

Agent-Class: TestAgent
Premain-Class: TestAgent
Can-Redine-Classes: true
Can-Retransform-Classes: true

將類打包為jar包

1. 編譯TestAgent
javac TestAgent.java2. jar打包
jar cvmf MANIFEST.MF xxx.jar TestAgent.class

動態附著到對應的JVM需要使用到JDK的Attach API
Main.java

import com.sun.tools.attach.VirtualMachine;public class Main 
{  public static void main(String[] args) throws Exception{  VirtualMachine vm = null;  String agentjarpath = "C:/Users/zhenghan.zh/Desktop/新建文件夾/xxx.jar"; //agentjar路徑  vm = VirtualMachine.attach("9730");//目標JVM的進程ID(PID)  vm.loadAgent(agentjarpath, "This is Args to the Agent.");  vm.detach();  }  
}

一旦運行這個Main方法, 其就會動態的附著到我們對應的JVM進程中,并為目標JVM加載我們指定的Agent,以達到我們想做的事情, 比如BTrace就為在附著到目標JVM后,開啟一個ServerSocket,以便達到與目標進程通訊的目的

Relevant Link:

http://ivanzhangwb.github.io/btrace-vm-attach-api/ 

?

3. Sun JVM Attach API

Sun JVM Attach API是Sun JVM中的一套非標準的可以連接到JVM上的API,從JDK6開始引入,除了Solaris平臺的Sun JVM支持遠程的Attach,在其他平臺都只允許Attach到本地的JVM上

0x1: 列出當前所有的JVM實例描述

package test;
import java.util.List;import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;public class Test 
{public static void main(String[] args) {List<VirtualMachineDescriptor> list = VirtualMachine.list();  for (VirtualMachineDescriptor vmd : list)  {  System.out.println("pid:" + vmd.id() + ":" + vmd.displayName());  }  }}
//tools.jar needs to be added to the IDE's library path and the program's classpath. The tools.jar file is found in the JDK's lib directory.

0x2: Attach到特定進程的JVM上,并加載Agent

//Attach到JVM上
VirtualMachine virtualmachine = VirtualMachine.attach(pid);  
//加載Agent
String javaHome = virtualmachine.getSystemProperties().getProperty("java.home");  
String agentPath = javaHome + File.separator + "jre" + File.separator + "lib" + File.separator + "management-agent.jar");  
File file = new File(agentPath);  
if(!file.exists())  
{  agentPath = javaHome + File.separator + "lib" + File.separator + "management-agent.jar";  file = new File(agentPath);  if(!file.exists())  throw new IOException("Management agent not found");  }  
}  agentPath = file.getCanonicalPath();  
try  
{  virtualmachine.loadAgent(agentPath, "com.sun.management.jmxremote");  
}  
catch(AgentLoadException e)  
{  throw new IOException(e);  
}  
catch(AgentInitializationException agentinitializationexception)  
{  throw new IOException(e);  
}  
Properties properties = virtualmachine.getAgentProperties();  
address = (String)properties.get("com.sun.management.jmxremote.localConnectorAddress");  
virtualmachine.detach(); 

0x3: Attach API底層實現(windows)

\openjdk\jdk\src\windows\classes\sun\tools\attach\WindowsAttachProvider.java

public VirtualMachine attachVirtualMachine(String vmid) throws AttachNotSupportedException, IOException
{checkAttachPermission();// AttachNotSupportedException will be thrown if the target VM can be determined// to be not attachable.
    testAttachable(vmid);return new WindowsVirtualMachine(this, vmid);
}

\openjdk\jdk\src\windows\classes\sun\tools\attach\WindowsVirtualMachine.java

WindowsVirtualMachine(AttachProvider provider, String id) throws AttachNotSupportedException, IOException
{//繼承HotSpotVirtualMachine
    super(provider, id);int pid;try {pid = Integer.parseInt(id);} catch (NumberFormatException x) {throw new AttachNotSupportedException("Invalid process identifier");}//先連接上目標JVMhProcess = openProcess(pid);// The target VM might be a pre-6.0 VM so we enqueue a "null" command// which minimally tests that the enqueue function exists in the target// VM.try {enqueue(hProcess, stub, null, null);} catch (IOException x) {throw new AttachNotSupportedException(x.getMessage());}
}

WindowsVirtualMachine繼承HotSpotVirtualMachine,先看看HotSpotVirtualMachine的loadAgent方法
\openjdk\jdk\src\share\classes\sun\tools\attach\HotSpotVirtualMachine.java

/*
* Load JPLIS agent which will load the agent JAR file and invoke
* the agentmain method.
*/
public void loadAgent(String agent, String options) throws AgentLoadException, AgentInitializationException, IOException
{String args = agent;if (options != null) {args = args + "=" + options;}try {loadAgentLibrary("instrument", args);} catch (AgentLoadException x) {throw new InternalError("instrument library is missing in target VM");} catch (AgentInitializationException x) {/** Translate interesting errors into the right exception and* message (FIXME: create a better interface to the instrument* implementation so this isn't necessary)*/int rc = x.returnValue();switch (rc) {case JNI_ENOMEM:throw new AgentLoadException("Insuffient memory");case ATTACH_ERROR_BADJAR:throw new AgentLoadException("Agent JAR not found or no Agent-Class attribute");case ATTACH_ERROR_NOTONCP:throw new AgentLoadException("Unable to add JAR file to system class path");case ATTACH_ERROR_STARTFAIL:throw new AgentInitializationException("Agent JAR loaded but agent failed to initialize");default :throw new AgentLoadException("Failed to load agent - unknown reason: " + rc);}}
}

loadAgentLibrary("instrument", args);

/*
* Load agent library
* If isAbsolute is true then the agent library is the absolute path
* to the library and thus will not be expanded in the target VM.
* if isAbsolute is false then the agent library is just a library
* name and it will be expended in the target VM.
*/
private void loadAgentLibrary(String agentLibrary, boolean isAbsolute, String options) throws AgentLoadException, AgentInitializationException, IOException
{InputStream in = execute("load",agentLibrary,isAbsolute ? "true" : "false",options);try {int result = readInt(in);if (result != 0) {throw new AgentInitializationException("Agent_OnAttach failed", result);}} finally {in.close();}
}

可以看到,Java在Attach到目標進行后,調用execute讓目標進行加載Agent類,我們繼續分析execute的實現方式,可以看到,JVM進程間通信是JVM Attach API的核心,JVM自身就預留了執行來自Attach進程的指令接口
\openjdk\jdk\src\windows\classes\sun\tools\attach\WindowsVirtualMachine.java

InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException
{assert args.length <= 3;        // includes null// create a pipe using a random nameint r = (new Random()).nextInt();String pipename = "\\\\.\\pipe\\javatool" + r;long hPipe = createPipe(pipename);// check if we are detached - in theory it's possible that detach is invoked// after this check but before we enqueue the command.if (hProcess == -1) {closePipe(hPipe);throw new IOException("Detached from target VM");}try {// enqueue the command to the process
        enqueue(hProcess, stub, cmd, pipename, args);// wait for command to complete - process will connect with the// completion status
        connectPipe(hPipe);// create an input stream for the pipePipedInputStream is = new PipedInputStream(hPipe);// read completion statusint status = readInt(is);if (status != 0) {// special case the load command so that the right exception is thrownif (cmd.equals("load")) {throw new AgentLoadException("Failed to load agent library");} else {throw new IOException("Command failed in target VM");}}// return the input streamreturn is;} catch (IOException ioe) {closePipe(hPipe);throw ioe;}
}

JVM的execute方法中調用了大量native方法,并且從代碼中可以看出,JVM Attach的進程間通信使用了管道進行通信

Relevant Link:

http://ayufox.iteye.com/blog/655761 
http://docs.oracle.com/javase/7/docs/jdk/api/attach/spec/com/sun/tools/attach/VirtualMachine.html
http://docs.oracle.com/javase/7/docs/jdk/api/attach/spec/index.html 

?

Copyright (c) 2015 LittleHann All rights reserved

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/287735.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/287735.shtml
英文地址,請注明出處:http://en.pswp.cn/news/287735.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

TCP之三次握手和四次揮手過程

1 TCP包頭里面的標志位 下圖為TCP頭部里面部分信息,入下標志位,每個標志位占一位。 標志位這里會涉及3個,ACK SYN FIN ACK:確認序號有效。 SYN:發起一個新連接。 FIN:釋放一個連接。 2 三次握手過程 第一次握手 Client將標志位SYN置1,隨機產生一個值seq=J,并將數…

Handler 機制分析

android 子線程和UI線程的交互主要使用Handler的方法進行通信。本文分析Handler機制 Handler 如何使用&#xff1f; Handler的使用比較簡單 public class MainActivity extends Activity{private Handler handler new Handler() { public void handleMessage(Message msg) { …

gearman mysql編譯_gearman初探(一、編譯和安裝)

gearman是一個任務分發系統&#xff0c;將計算比較耗時的任務分發給不同的機器專門進行計算&#xff0c;而任務發起的初始程序不必等待這些任務完成就可以返回而繼 續執行。筆者最開始做PHP郵件發送的時候&#xff0c;因為郵件發送耗時比較長&#xff0c;這時PHP腳本就會被阻塞…

《假如編程是魔法之零基礎看得懂的Python入門教程 》——(四)了解魔法百寶箱列表、字典及基本數據類型

學習目標 了解魔法世界中可更改容器——變量了解魔法世界的基本數值類型——字符串、整數了解魔法百寶箱——字典、列表了解列表如何添加值了解字典如何添加值了解字典與列表定義的不同符號 目錄 第一篇&#xff1a;《假如編程是魔法之零基礎看得懂的Python入門教程 》——&…

TCP協議之如何保證傳輸的可靠性

一、問題 TCP協議之如何保證傳輸的可靠性?我們先看下TCP的頭部圖片和TCP頭部的字段 /*TCP頭定義,共20個字節*/ typedef struct _TCP_HEADER {short m_sSourPort;       // 源端口號16bitshort m_sDestPort;       // 目的端口號16bitunsigned int …

【工具篇】在Mac上開發.Net Core需要的工具

微信公眾號&#xff1a;趣編程ACE關注可了解更多的.NET日常開發技巧,如需幫助&#xff0c;請后臺留言&#xff1b;[如果覺得本公眾號對您有幫助&#xff0c;歡迎關注]在Mac上開發.Net Core需要的工具如果您是一個.NET 開發者&#xff0c;想從Windows切換到Mac上開發.NET或者您已…

【Pix4d精品教程】Pix4Dmapper完整航測內業操作流程手把手圖文教程

1. 作業流程圖 2. 原始資料準備 原始資料包括影像數據、POS數據以及控制點數據。 確認原始數據的完整性,檢查獲取的影像中有沒有質量不合格的相片。同時查看POS數據文件,主要檢查航帶變化處的相片號,防止POS數據中的相片號與影像數據相片號不對應,出現不對應情況應手動調…

關于構造函數和this調用的思考

文中一系列思考和內容引發自以下問題&#xff1a;我需要在一個類的構造函數中調用另一個對象的構造函數&#xff0c;并使用this初始化其中的一個引用成員。 主要遇到的問題&#xff1a; 1. 構造函數的初始化列表中能訪問this嗎&#xff1f; 很明顯c創建一個對象分為兩部分&…

mysql semi join_MySQL 5.6 Semi join優化之materialization strategy

8月 24, 2014 |Nix.Huang考慮如下查詢&#xff1a;select * from Countrywhere Country.code IN (select City.Countryfrom Citywhere City.Population > 7*1000*1000)and Country.continentEurope這個子查詢是非相關子查詢&#xff0c;我們能和外層循環獨立的執行它&#x…

【ArcGIS風暴】何為動態投影?這次全面為您揭開ArcGIS中動態投影的神秘面紗!

本課程配套藍光視頻: 【ArcGIS風暴】GIS動態投影問題 GISer們都見過以下警告,該警告的原因是當前加載的數據的坐標系和當前數據框坐標系不一致導致的,核心問題是地理坐標系不一致。如當前數據的坐標系是GCS_Xian_1980,而數據框的坐標系有可能是WGS_1984等,總之跟要加載的數…

《假如編程是魔法之零基礎看得懂的Python入門教程 》——(五)我的魔法竟然有了一絲邏輯

學習目標 了解魔法世界中的結構表現——縮進了解魔法世界的邏輯判斷——if了解魔法世界的多次邏輯判斷——ifelse嵌套了解魔法世界中的邏輯運算——且 and 與或 or 推薦 1.《備受好評的看得懂的C語言入門教程》 目錄 第一篇&#xff1a;《假如編程是魔法之零基礎看得懂的P…

類和類之間的關系

一、類和類之間的關系 UML類圖中&#xff0c;常見以下幾種關系: 1、泛化&#xff08;Generalization&#xff09; 是一種繼承關系&#xff0c;比如動物類和老虎類&#xff0c;老虎繼承動物&#xff0c;子類如何特化父類的所有特征和行為 箭頭指向:帶三角箭頭的實線&#xff0…

Java SpringMvc+hibernate架構中,調用Oracle中的sp,傳遞數組參數

一、問題 我們調用數據&#xff0c;大都是可以直接獲取表中的數據&#xff0c;或者用復雜點的sql語句組成的。但是&#xff0c;有時候&#xff0c;當這樣達不到我們要的全部數據的時候&#xff0c;這時&#xff0c;我們就用到了存儲過程【sp】&#xff0c;如果sp需要參數是數組…

js模擬blur

<div></div> 某個事件給div加個屬性 $(div).attr(wait,true); $(div).click(function() { if(false!$(this).attr(wait)) return false; })轉載于:https://www.cnblogs.com/cndxk/p/4788414.html

中國第一朵企業云

本文講的是中國第一朵企業云&#xff0c;【IT168 資訊】算起來&#xff0c;中國中化集團公司的ERP完全運行在“云”上已經一個多月了&#xff0c;每每提到這個“創舉”&#xff0c;信息技術部總經理彭勁松顯得有些興奮&#xff0c;卻仍然很謹慎。作為中國第一家企業云的實踐者&…

查缺補漏系統學習 EF Core 6 - 實體配置

推薦關注「碼俠江湖」加星標&#xff0c;時刻不忘江湖事這是 EF Core 系列的第二篇文章&#xff0c;上一篇文章講解了 EF Core 的一些基礎概念&#xff0c;這一篇文章主要圍繞實體屬性的配置。點擊上方或后方藍字&#xff0c;閱讀 EF Core 系列合集。實體配置配置實體的目的&am…

【ArcGIS風暴】捕捉VS經典捕捉,誰更有用武之地?

幾乎所有的GIS軟件都具有捕捉功能!今天我們一起來聊一聊ArcGIS軟件中的捕捉功能吧。 ArcGIS軟件中有兩個重要的捕捉工具:捕捉和經典捕捉。 目錄 一、捕捉(Snapping) 1、捕捉類型 2、捕捉選項

mysql innodb 索引 延遲更新_Mysql覆蓋索引與延遲關聯

延遲關聯&#xff1a;通過使用覆蓋索引查詢返回需要的主鍵,再根據主鍵關聯原表獲得需要的數據。為什innodb的索引葉子節點存的是主鍵&#xff0c;而不是像myisam一樣存數據的物理地址指針&#xff1f;如果存的是物理地址指針不就不需要二次查找了嗎&#xff0c;根據myisam和inn…

Android之在筆記本電腦adb devices識別不了oppo A9手機(設備管理器ADB Interface里面有個黃色感嘆號)

1 問題 記本電腦adb devices識別不了oppo A9手機&#xff08;設備管理器ADB Interface里面有個黃色感嘆號&#xff09; 圖片如下 2 分析 很明顯這里是驅動問題&#xff0c;ADB Interface有感嘆號提示&#xff0c;所以這里需要解決驅動問題 3 解決辦法 1&#xff09;可以嘗試…

《假如編程是魔法之零基礎看得懂的Python入門教程 》——(六)精簡魔法更強大

學習目標 了解對相似邏輯的簡化編寫——循環 推薦 1.《備受好評的看得懂的C語言入門教程》 目錄 第一篇&#xff1a;《假如編程是魔法之零基礎看得懂的Python入門教程 》——&#xff08;一&#xff09;既然你選擇了這系列教程那么我就要讓你聽得懂 第二篇&#xff1a;《假…