Java Agents代理是什么
表示Java Agents的類(lèi)顯然只不過(guò)是Java API庫(kù)中的任何其他類(lèi)。但是,讓它們與眾不同的是,它們遵循某種約定,這種約定使Java代碼能夠攔截JVM中運(yùn)行的另一個(gè)應(yīng)用程序。其目的只是讓代理調(diào)查或修改字節(jié)碼。這是一個(gè)強(qiáng)大但不可思議的特性,超出了Java程序通常的功能范圍。在某種程度上,它可以闖入一個(gè)程序,修改字節(jié)碼或造成混亂。請(qǐng)理解,這不是添加到Java中的新技術(shù)或功能。自JDK1.5以來(lái),它一直是庫(kù)的一部分。這意味著使用它們也有一些真正的好處。但是,在討論它們的優(yōu)點(diǎn)以及如何使用它們之前,讓我們先看看在Java中哪里可以找到它們。
一、Java Agents 和 Instrumentation
Java agent是Java Instrumentation API的一部分。檢測(cè)API提供了一種修改方法字節(jié)碼的機(jī)制。這可以靜態(tài)和動(dòng)態(tài)地完成。這意味著我們可以通過(guò)向程序中添加代碼來(lái)更改程序,而不必涉及程序的實(shí)際源代碼。結(jié)果可能會(huì)對(duì)應(yīng)用程序的整體行為產(chǎn)生重大影響。
Java agent和instrumentation API位于名為 Java.lang.intrumentation 的包中。
二、Java agent的使用
Java agent可以有多種用途,如面向方面編程(AOP)、變異測(cè)試、評(píng)測(cè)等。AOP通常會(huì)在不更改代碼的情況下向現(xiàn)有程序添加日志記錄或安全性等行為。它使用Java代理來(lái)操作字節(jié)碼,并將其功能與程序結(jié)合起來(lái)。監(jiān)視JVM級(jí)別的參數(shù),如對(duì)象創(chuàng)建、垃圾收集、線(xiàn)程執(zhí)行等,是探查器的工作。評(píng)測(cè)工具顯著地使用Java代理評(píng)測(cè)執(zhí)行中程序的JVM參數(shù)。
還有許多其他情況下,Java agent和instrumentation API非常方便。
三、如何編寫(xiě)Java代理
實(shí)現(xiàn)Java agent的類(lèi)必須實(shí)現(xiàn)一個(gè)名為
public static void premain(String agentArgs, Instrumentation inst)
此方法構(gòu)成代理的入口點(diǎn),就像常規(guī)Java程序的入口點(diǎn)是主方法一樣。
JVM初始化后,調(diào)用 premain 方法;這表示代理。可以有幾個(gè)這樣的代理;因此,將根據(jù)JVM初始化期間指定的代理的順序調(diào)用每個(gè) premain 方法。如果找不到特定的 premain 方法,JVM會(huì)依次調(diào)用 premain 方法的重載版本,例如
public static void premain(String agentArgs)
代理類(lèi)還可能包含JVM在agent啟動(dòng)后通常使用的方法,例如
public static void agentmain(String agentArgs, instrumentation inst)
或者,它的重載版本
public static void agentmain(String agentArgs)
這是JVM的典型例程,一旦該例程完成,就會(huì)調(diào)用 main 方法。
另一件重要的事情是,Java代理在開(kāi)發(fā)期間必須在資源目錄的 META-INF 文件夾中包含 MANIFEST.MF 文件。此文件包含有關(guān)包分發(fā)的元數(shù)據(jù)信息。此文件作為其JAR打包的一部分包含。 MANIFEST.MF 文件中包含的屬性提供了有關(guān)為什么需要這樣做的線(xiàn)索。這些屬性如下所示:
Premain-class:此屬性定義代理類(lèi)。如果未定義此屬性,JVM將中止。Agent-class:它定義了在JVM啟動(dòng)后啟動(dòng)Java代理的機(jī)制。如果此屬性未定義,代理將不會(huì)啟動(dòng)。Can-Redefine-Classes:這定義了代理重新定義類(lèi)的能力。該值可以是true或false。Can-Retransform-Classes:這定義了代理重新傳輸類(lèi)的能力。該值可以是true或false。Can-Set-Native-Method-Prefix:這定義了代理設(shè)置本機(jī)方法前綴的能力。該值可以是true或false。Boot-Class-Path:定義引導(dǎo)類(lèi)加載程序的搜索路徑列表。
一個(gè)簡(jiǎn)單的例子:
探查器工具通常通過(guò)從JVM提取信息來(lái)報(bào)告運(yùn)行時(shí)Java對(duì)象的不同參數(shù)。這些參數(shù)包括關(guān)于使用檢測(cè)框架的對(duì)象的內(nèi)存使用等信息。
1. 這里我們使用 premain 方法創(chuàng)建一個(gè)代理類(lèi)。
2. 傳遞給 premain 方法的檢測(cè)實(shí)例將提供有關(guān)對(duì)象大小的信息。
3. 將代理類(lèi)與 MANIFEST.MF 文件一起打包到JAR文件中。
4. 使用命令行參數(shù)將代理傳遞給JVM。
這是我們將在示例中使用的示例類(lèi)。這沒(méi)什么特別的。
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");
}
}
四、代理類(lèi)
帶有 premain 方法的instrumentation agent類(lèi)用于檢索我們需要的信息。插裝接口的實(shí)現(xiàn)被傳遞給 premain 方法。我們使用由instrumentation接口定義的 getObjectSize 方法來(lái)獲取運(yùn)行時(shí)主對(duì)象的內(nèi)存使用情況。
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()))
}
}
之后,我們必須創(chuàng)建 MANIFEST.MF 文件。這只是一個(gè)文本文件,我們?cè)谄渲蟹胖门c代理類(lèi)相關(guān)的信息。JVM將使用它來(lái)加載代理。該文件通常存儲(chǔ)在 META-INF 目錄中。
我們的示例所需的內(nèi)容非常基本:
Manifest-Version: 1.0 Premain-Class: com.mano.examples.MyAgentClass
現(xiàn)在,編譯所有Java文件以創(chuàng)建類(lèi)文件。最后,創(chuàng)建JAR文件,如下所示:
jar -cmf META-INF/MANIFEST.MF myagent.jar com/mano/examples/ MyAgentClass.class
五、部署Java Agents
創(chuàng)建代理后,它將作為JAR文件部署。清單文件中的屬性指定將加載以啟動(dòng)代理的代理類(lèi)。請(qǐng)注意,啟動(dòng)代理有很多方法:使用命令行、運(yùn)行時(shí)或作為JAR可執(zhí)行文件。我們將在這里使用命令行。
使用命令行運(yùn)行Agents代理
命令行是:
java -javaagent:myagent.jar -cp . com.mano.examples.Main
這表示 premain 方法將在應(yīng)用程序執(zhí)行之前運(yùn)行,并創(chuàng)建 Main 實(shí)例的大小。
結(jié)論:
儀器API所提供的功能可以進(jìn)行多種創(chuàng)新。AOP是一個(gè)簡(jiǎn)單的例子。雖然Java代理和Java Instrumentation API在應(yīng)用程序開(kāi)發(fā)中不經(jīng)常使用,但是關(guān)于它的全部?jī)?nèi)容的想法可以澄清Java的許多其他方面。這里給出的代碼示例是初步的,只是為了說(shuō)明如何創(chuàng)建代理。
到此這篇關(guān)于Java Agents代理是什么的文章就介紹到這了,更多相關(guān)Java Agents代理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實(shí)現(xiàn)字符串倒序輸出的四種方法匯總
這篇文章主要介紹了Java實(shí)現(xiàn)字符串倒序輸出的四種方法匯總,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
mybatis分割字符串并循環(huán),實(shí)現(xiàn)in多個(gè)參數(shù)的操作
這篇文章主要介紹了mybatis分割字符串并循環(huán),實(shí)現(xiàn)in多個(gè)參數(shù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
通過(guò)案例了解靜態(tài)修飾符static使用場(chǎng)景
這篇文章主要介紹了通過(guò)案例了解靜態(tài)修飾符static使用場(chǎng)景,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
解決SpringMVC獲取請(qǐng)求參數(shù)亂碼問(wèn)題
在使用SpringMVC和thymeleaf進(jìn)行請(qǐng)求參數(shù)處理時(shí),可能會(huì)遇到亂碼問(wèn)題,對(duì)于GET方法亂碼,可通過(guò)修改Tomcat的server.xml文件,添加URIEncoding="UTF-8"解決,而POST方法亂碼,則需在web.xml配置SpringMVC提供的過(guò)濾器2024-11-11
javaBean的基礎(chǔ)知識(shí)及常見(jiàn)亂碼解決方法
這篇文章主要介紹了javaBean的基礎(chǔ)知識(shí)及常見(jiàn)亂碼解決方法的相關(guān)資料,需要的朋友可以參考下2017-03-03
Java源碼難點(diǎn)突破Lambda表達(dá)式執(zhí)行原理
這篇文章主要為大家介紹了Java難點(diǎn)突破Lambda表達(dá)式執(zhí)行原理分析及示例的實(shí)現(xiàn)源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03
MybatisPlus分頁(yè)排序查詢(xún)字段帶有下劃線(xiàn)的坑及解決
這篇文章主要介紹了MybatisPlus分頁(yè)排序查詢(xún)字段帶有下劃線(xiàn)的坑及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12

