国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Java 5 特性 Instrumentation 實踐

2019-11-18 13:36:31
字體:
來源:轉載
供稿:網友

    Instrumentation 是 java 5 提供的新特性。使用 Instrumentation,開發者可以構建一個代理,用來監測運行在 JVM 上的程序。監測一般是通過在執行某個類文件之前,對該類文件的字節碼進行適當修改進行的。下文將通過一個具體的例子,來展示 java.lang.instrument 包的工作原理,并且實現了一個測量函數運行時間的代理。

簡介

    不使用instrumentation 來測量函數運行時間的傳統方法是:在函數調用之前記錄當前系統時間,在函數調用完成之后再次記錄當前系統時間(為了簡化描述,本文不考慮虛擬機進程映射到本地操作系統進程時造成的計時誤差,詳見Use the JVM PRofiler Interface for accurate timing)。最后將兩次數據的差值作為本次函數運行時間返回。這種方法的弱點在于:

  • 用于性能測量的語句直接夾雜在邏輯代碼中
  • 用于性能測量的邏輯是重復的,沒有做到代碼重用。

使用 instrumentation 提供的功能,結合 Apache 開源項目 BCEL,本文將實現一個用于測量函數運行時間的代理。通過代理技術,用于性能測量的語句與業務邏輯完全分離,同時該代理可以用于測量任意類的任意方法的運行時間,大大提高了代碼的重用性。

Greeting 代理

在實現函數運行時間測量代理之前,我們先通過實現一個簡單的 Greeting 代理,介紹一下 Java 5 中 instrumentation 的原理。每個代理的實現類必須實現 ClassFileTransformer 接口。這個接口提供了一個

public byte[] transform(    ClassLoader loader,     String className,     Class cBR,     java.security.ProtectionDomain pD,     byte[] classfileBuffer) throws IllegalClassFormatException            

方法。通過這個方法,代理可以得到虛擬機載入的類的字節碼(通過 classfileBuffer 參數)。代理的各種功能一般是通過操作這一串字節碼得以實現的。同時還需要提供一個公共的靜態方法:
static void premain(String agentArgs, Instrumentation inst)

。一般會在這個方法中創建一個代理對象,通過參數 inst 的 addTransformer() 方法,將創建的代理對象再傳遞給虛擬機。這個方法是一個入口方法,有點類似于一般類的 main 方法。圖1展示了代理工作的原理


圖1 代理工作原理
Java 5 特性 Instrumentation 實踐(圖一)

可以看到,多個代理可以同時執行。這多個代理的 premain 方法將按照代理指定的順序被依次調用。

下面的代碼片斷,演示了 Greeting 代理的 transform 方法。在該方法中我們對 agent 的行為進行了簡單的定制——輸出需要該代理監測的類名。


列表1 輸出 Hello, someClass

    public byte[] transform(ClassLoader loader,              String className,              Class cBR, java.security.ProtectionDomain pD,              byte[] classfileBuffer)     throws IllegalClassFormatException  {    System.out.println("Hello,/t", className);    return null;   }               

transform 函數的最后,返回 null 值,表示不需要進行類字節碼的轉化。定制完代理的行為之后,創建一個 greeting 代理的實例,將該實例傳遞給虛擬機。


列表2 將 Greeting 代理的實例傳遞給虛擬機

public static void premain(String options, Instrumentation ins) {    if (options != null) {System.out.printf("I've been called with options: /"%s/"/n", options);    }    else       System.out.println("  I've been called with no options.");    ins.addTransformer(new Greeting());              }

options 參數是通過命令行傳遞進來的,類似于調用 main 函數時傳遞的參數。被傳遞進來的命令行參數是一個完整的字符串,不同于 main 方法,該字符串的解析完全由代理自己負責。列表 3 展示了如何使用命令行調用代理:



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 交口县| 酉阳| 安徽省| 金山区| 长阳| 射洪县| 古交市| 安福县| 平南县| 荥经县| 吴川市| 建湖县| 泰州市| 宣城市| 巨野县| 青龙| 宣汉县| 呈贡县| 桂东县| 宜昌市| 林甸县| 镇安县| 嘉鱼县| 柞水县| 高雄市| 平阴县| 沐川县| 平江县| 宜州市| 古浪县| 大姚县| 漳州市| 新民市| 定陶县| 铜山县| 特克斯县| 台湾省| 木兰县| 荥经县| 宜兰市| 精河县|