本篇內(nèi)容介紹了“不用Jar包的Agent的優(yōu)點(diǎn)有哪些”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
成都創(chuàng)新互聯(lián)是一家以重慶網(wǎng)站建設(shè)公司、網(wǎng)頁(yè)設(shè)計(jì)、品牌設(shè)計(jì)、軟件運(yùn)維、成都網(wǎng)站推廣、小程序App開(kāi)發(fā)等移動(dòng)開(kāi)發(fā)為一體互聯(lián)網(wǎng)公司。已累計(jì)為成都搬家公司等眾行業(yè)中小客戶(hù)提供優(yōu)質(zhì)的互聯(lián)網(wǎng)建站和軟件開(kāi)發(fā)服務(wù)。
提起 JavaAgent,很多人都說(shuō)幾句,就像古龍武俠小說(shuō)里的「孔雀翎」,威力很大,江湖上都是它的傳說(shuō)。但真的見(jiàn)識(shí)過(guò)的人并沒(méi)幾個(gè)。
JavaAgent 雖說(shuō)沒(méi)這么神秘,但也一直給人曲高和寡的感覺(jué),除了一些中間件產(chǎn)品、大型的框架中使用外,在業(yè)務(wù)中一直很少出現(xiàn)。
原因可能有很多,一來(lái)是可能確實(shí)不需要,再者需要開(kāi)發(fā)獨(dú)立的 Agent Jar 文件,在 Jar 內(nèi)對(duì)類(lèi)的 transform 開(kāi)發(fā)也并不容易。
我們知道,無(wú)論是啟動(dòng)時(shí)的 Java Agent,還是運(yùn)行時(shí)的動(dòng)態(tài) attach 到遠(yuǎn)程JVM, 都是為了拿到 Instrument,對(duì) class 的字節(jié)碼進(jìn)行修改。這么底層的東西,當(dāng)然使用起來(lái)讓人不太容易下手。
不過(guò)就像機(jī)器語(yǔ)言不方便,人們發(fā)明了匯編語(yǔ)言,又發(fā)現(xiàn)了高級(jí)語(yǔ)言。對(duì)于字節(jié)碼的操作也類(lèi)似,人們覺(jué)得直接操作字節(jié)碼有難度,而且需要深入理解 JVM 規(guī)范,具體什么位置多少字節(jié)代表啥,這不是一般人喜歡的,于是 ASM 框架出現(xiàn)了;但還是有規(guī)范的影子,不太「高級(jí)」,于是又出現(xiàn)了Javassist 這一類(lèi)的「高級(jí)」工具。
我們今天要說(shuō)的這個(gè)工具,和 Javassist 類(lèi)似,都提供了更高層的API,來(lái)操作class,對(duì)普通程序員更友好,除此之外呢?
就像今天人們購(gòu)物、讀書(shū)等,都更相信專(zhuān)業(yè)的平臺(tái)、或者專(zhuān)家的推薦,像XX嚴(yán)選,XX讀書(shū)會(huì)推薦。今天說(shuō)的這個(gè)工具是Duke 的推薦,對(duì),就是它, Java 的吉祥物,這個(gè)小胖子。今天的這個(gè)工具在 2015年被 Oracle 評(píng)選為「Duke's Choice award」。
除了Duke,框架也得到了眾多開(kāi)發(fā)者的認(rèn)可,每年有七千多萬(wàn)次的下載。
這個(gè)工具是:Bytebuddy。
從名字你就看的出來(lái),它立志要做字節(jié)碼的好伙伴。所以在很多開(kāi)源框架里也能看到它的身影。
既然已經(jīng)有了不少的工具, byteBuddy能帶來(lái)什么不一樣呢?
除了API 上的簡(jiǎn)潔易操作,官方自己也大字強(qiáng)調(diào)了運(yùn)行時(shí)動(dòng)態(tài)的「代碼生成和字節(jié)碼操作」,不需要再借助 Java 編譯器。
來(lái)看看官網(wǎng)是怎么自我介紹的,后面再附上幾個(gè)代碼片段,就能很快 Get 到了。
官網(wǎng):https://bytebuddy.net/
Byte Buddy is a code generation and manipulation library for creating and modifying Java classes during the runtime of a Java application and without the help of a compiler. Other than the code generation utilities that ship with the Java Class Library, Byte Buddy allows the creation of arbitrary classes and is not limited to implementing interfaces for the creation of runtime proxies. Furthermore, Byte Buddy offers a convenient API for changing classes either manually, using a Java agent or during a build.
閱讀理解開(kāi)始。重點(diǎn)你一定會(huì)看到了:
「code generation」
「creating and modifying Java classes」
作者貼心的加了一段小字來(lái)描述框架的優(yōu)勢(shì)。選重點(diǎn)的說(shuō)就是:
鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)
不需要理解字節(jié)碼,也不需要理解class 文件格式
API 非侵入,設(shè)計(jì)簡(jiǎn)潔易懂
高度可定制,可以任意自定義
我自己認(rèn)為該把這點(diǎn)也加上,不寫(xiě) Java Agent 也可以 Attach 到 JVM 上,把 ByteBuddy 自己當(dāng)成一個(gè)Agent,運(yùn)行時(shí)直接install。Cool。
不寫(xiě)JVM Agent 也能對(duì)類(lèi)攔截和修改,我們來(lái)認(rèn)識(shí)下揭開(kāi)字節(jié)碼修改黑魔法的家伙。
為了對(duì) Class 進(jìn)行一些操作,我們一般都離不了 JVM Agent。不管是啟動(dòng)時(shí)直接連接,還是運(yùn)行時(shí)動(dòng)態(tài)的 Attach到對(duì)應(yīng)的JVM 上,都需要 Agent。也就是我們熟悉的premain 和 agentmain 的觸發(fā)入口,通過(guò)它們,我們才能拿到 Instrumentation,從而進(jìn)行 transform和 redeine。
但這個(gè)東西的使用,給人總是「陽(yáng)春白雪」的感覺(jué),讓人覺(jué)得是黑魔法一樣,一般不會(huì)輕易嘗試使用。
有了ByteBuddy,就不用再羨慕一些框架的「運(yùn)行時(shí)增強(qiáng)」,「動(dòng)態(tài)織入」等等,都可以實(shí)現(xiàn)。
如何上手呢?
只需要下載 Jar 文件或者 Maven 添加依賴(lài)之后就能狂奔了。
比如官方的這個(gè) HelloWorld
Class<?> dynamicType = new ByteBuddy() .subclass(Object.class) .method(ElementMatchers.named("toString")) .intercept(FixedValue.value("Hello World!")) .make() .load(getClass().getClassLoader()) .getLoaded(); assertThat(dynamicType.newInstance().toString(), is("Hello World!"));
直接把 Object 的 toString 方法改寫(xiě)了。
再比如我們可以在開(kāi)發(fā) Java Agent的時(shí)候使用這個(gè)伙計(jì)
public static void premain(String args, Instrumentation inst) { AgentBuilder agentBuilder = new AgentBuilder.Default(); AgentBuilder.Transformer transformer = new AgentBuilder.Transformer() { public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule) { String className = typeDescription.getCanonicalName(); builder = builder.method(ElementMatchers.any())//匹配任意方法 .intercept(MethodDelegation.to(new SimplePackageInstanceMethodInterceptor())); return builder; } }; agentBuilder = agentBuilder.type(ElementMatchers.nameStartsWith("com.example.hello.sample")).transform(transformer); agentBuilder.installOn(inst); }
在類(lèi)里進(jìn)行攔截匹配的時(shí)候,可以通過(guò)類(lèi)名來(lái)限定,同時(shí)以不同的模式去匹配方法名等,這里的ElementMatchers可以用在類(lèi)名與方法名等匹配場(chǎng)景中
//ElementMatchers.named("abc") // 特定名稱(chēng)的方法 //ElementMatchers.nameStartsWith("hello") // 以什么開(kāi)頭的 //ElementMatchers.nameEndsWith("test") // 以什么結(jié)尾的
我們看到前面的代碼中 agentBuilder.installOn(inst);
通過(guò) JavaAgent的Instrument 進(jìn)行類(lèi)修改。
AgentBuilder 還提供了一個(gè)神奇的方法:
agentBuilder.installOnByteBuddyAgent();
這樣無(wú)須提供 Jar 文件也一樣能實(shí)現(xiàn)運(yùn)行時(shí)增強(qiáng)。不過(guò)需要注意,這樣使用時(shí),一定要先執(zhí)行這行代碼,這也是其實(shí)現(xiàn)的秘密:
ByteBuddyAgent.install();
因?yàn)?ByteBuddy 自己做為一個(gè) Jar 也 Attach ,然后再將其它后續(xù)的增強(qiáng)代碼加入,像不像「特洛伊木馬」 :)
另外, ByteBuddy 還支持類(lèi)似于 AOP 的 Advice實(shí)現(xiàn),在攔截指定方法后可以實(shí)現(xiàn)OnMethodEnter 和 OnMethodExit 的控制,在這其中,可以完成繞過(guò)用戶(hù)代碼,執(zhí)行自定義內(nèi)容的邏輯。
咱們?cè)陂_(kāi)始的時(shí)候,還提到了代碼的生成。這在 ByteBuddy 看來(lái)也是易如反掌。
和上面的代碼一樣,先要拿到 AgentBuilder,之后在執(zhí)行 tranform的時(shí)候,直接指定方法名,以及對(duì)應(yīng)的參數(shù),訪問(wèn)控制符等。
DynamicType.Builder.MethodDefinition.ExceptionDefinition<?> hello = builder.defineMethod(methodName, types, Visibility.PUBLIC) .withParameters(m.getParameters().asTypeList());
再比如在運(yùn)行時(shí)給一個(gè)方法增加注解,
builder.method(ElementMatchers.named("methodName")).intercept(SuperMethodCall.INSTANCE) .annotateMethod(AnnotationDescription.Builder.ofType(TestAnnotation.class) .define("testValue", 123).build());
是不是功能很強(qiáng)大?
“不用Jar包的Agent的優(yōu)點(diǎn)有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
當(dāng)前標(biāo)題:不用Jar包的Agent的優(yōu)點(diǎn)有哪些
文章出自:http://aaarwkj.com/article14/gjoede.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營(yíng)銷(xiāo)、ChatGPT、外貿(mào)建站、全網(wǎng)營(yíng)銷(xiāo)推廣、網(wǎng)站策劃、定制網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)