Java Agents代理是什麼

表示Java Agents的類顯然隻不過是Java API庫中的任何其他類。但是,讓它們與眾不同的是,它們遵循某種約定,這種約定使Java代碼能夠攔截JVM中運行的另一個應用程序。其目的隻是讓代理調查或修改字節碼。這是一個強大但不可思議的特性,超出瞭Java程序通常的功能范圍。在某種程度上,它可以闖入一個程序,修改字節碼或造成混亂。請理解,這不是添加到Java中的新技術或功能。自JDK1.5以來,它一直是庫的一部分。這意味著使用它們也有一些真正的好處。但是,在討論它們的優點以及如何使用它們之前,讓我們先看看在Java中哪裡可以找到它們。

一、Java Agents 和 Instrumentation

Java agentJava Instrumentation API的一部分。檢測API提供瞭一種修改方法字節碼的機制。這可以靜態和動態地完成。這意味著我們可以通過向程序中添加代碼來更改程序,而不必涉及程序的實際源代碼。結果可能會對應用程序的整體行為產生重大影響。

Java agentinstrumentation API位於名為 Java.lang.intrumentation 的包中。

二、Java agent的使用

Java agent可以有多種用途,如面向方面編程(AOP)、變異測試、評測等。AOP通常會在不更改代碼的情況下向現有程序添加日志記錄或安全性等行為。它使用Java代理來操作字節碼,並將其功能與程序結合起來。監視JVM級別的參數,如對象創建、垃圾收集、線程執行等,是探查器的工作。評測工具顯著地使用Java代理評測執行中程序的JVM參數。

還有許多其他情況下,Java agentinstrumentation API非常方便。

三、如何編寫Java代理

實現Java agent的類必須實現一個名為

public static void premain(String agentArgs, Instrumentation inst)


此方法構成代理的入口點,就像常規Java程序的入口點是主方法一樣。

JVM初始化後,調用 premain 方法;這表示代理。可以有幾個這樣的代理;因此,將根據JVM初始化期間指定的代理的順序調用每個 premain 方法。如果找不到特定的 premain 方法,JVM會依次調用 premain 方法的重載版本,例如

public static void premain(String agentArgs)


代理類還可能包含JVM在agent啟動後通常使用的方法,例如

public static void agentmain(String agentArgs,
   instrumentation inst)


或者,它的重載版本

public static void agentmain(String agentArgs)


這是JVM的典型例程,一旦該例程完成,就會調用 main 方法。

另一件重要的事情是,Java代理在開發期間必須在資源目錄的 META-INF 文件夾中包含 MANIFEST.MF 文件。此文件包含有關包分發的元數據信息。此文件作為其JAR打包的一部分包含。 MANIFEST.MF 文件中包含的屬性提供瞭有關為什麼需要這樣做的線索。這些屬性如下所示:

  • Premain-class :此屬性定義代理類。如果未定義此屬性,JVM將中止。
  • Agent-class :它定義瞭在JVM啟動後啟動Java代理的機制。如果此屬性未定義,代理將不會啟動。
  • Can-Redefine-Classes :這定義瞭代理重新定義類的能力。該值可以是truefalse
  • Can-Retransform-Classes :這定義瞭代理重新傳輸類的能力。該值可以是truefalse
  • Can-Set-Native-Method-Prefix :這定義瞭代理設置本機方法前綴的能力。該值可以是truefalse
  • Boot-Class-Path :定義引導類加載程序的搜索路徑列表。

一個簡單的例子:

探查器工具通常通過從JVM提取信息來報告運行時Java對象的不同參數。這些參數包括關於使用檢測框架的對象的內存使用等信息。

1. 這裡我們使用 premain 方法創建一個代理類。

2. 傳遞給 premain 方法的檢測實例將提供有關對象大小的信息。

3. 將代理類與 MANIFEST.MF 文件一起打包到JAR文件中。

4. 使用命令行參數將代理傳遞給JVM。

這是我們將在示例中使用的示例類。這沒什麼特別的。

package com.mano.examples;
public class Main {
   public static void greet(String msg){
      System.out.println(msg);
   }
   public static void main(String[] args){
      greet("Hello Agents");
   }
}

四、代理類

帶有 premain 方法的instrumentation agent類用於檢索我們需要的信息。插裝接口的實現被傳遞給 premain 方法。我們使用由instrumentation接口定義的 getObjectSize 方法來獲取運行時主對象的內存使用情況。

package com.mano.examples;
import java.lang.instrument.Instrumentation;
public class MyAgentClass {
   public static void premain(String agentArgs,
      Instrumentation inst) {
      System.out.println(inst.getObjectSize
         (new Main()))
   }
}

之後,我們必須創建 MANIFEST.MF 文件。這隻是一個文本文件,我們在其中放置與代理類相關的信息。JVM將使用它來加載代理。該文件通常存儲在 META-INF 目錄中。

我們的示例所需的內容非常基本:

Manifest-Version: 1.0
Premain-Class: com.mano.examples.MyAgentClass

現在,編譯所有Java文件以創建類文件。最後,創建JAR文件,如下所示:

jar -cmf META-INF/MANIFEST.MF myagent.jar com/mano/examples/
   MyAgentClass.class

五、部署Java Agents

創建代理後,它將作為JAR文件部署。清單文件中的屬性指定將加載以啟動代理的代理類。請註意,啟動代理有很多方法:使用命令行、運行時或作為JAR可執行文件。我們將在這裡使用命令行。

使用命令行運行Agents代理

命令行是:

java -javaagent:myagent.jar -cp . com.mano.examples.Main

這表示 premain 方法將在應用程序執行之前運行,並創建 Main 實例的大小。

結論:

儀器API所提供的功能可以進行多種創新。AOP是一個簡單的例子。雖然Java代理和Java Instrumentation API在應用程序開發中不經常使用,但是關於它的全部內容的想法可以澄清Java的許多其他方面。這裡給出的代碼示例是初步的,隻是為瞭說明如何創建代理。

到此這篇關於Java Agents代理是什麼的文章就介紹到這瞭,更多相關Java Agents代理內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: