摘要:運(yùn)行時(shí)修改字節(jié)碼需求在運(yùn)行時(shí)動(dòng)態(tài)修改某個(gè)類的字節(jié)碼文件,不重啟服務(wù)器。方案字節(jié)碼修改框架有很多第三方的字節(jié)碼修改框架,由于前期接觸了產(chǎn)品所以決定使用框架,相對(duì)而言更為簡(jiǎn)單,但是效率較低。
運(yùn)行時(shí)修改字節(jié)碼
需求:在運(yùn)行時(shí)動(dòng)態(tài)修改某個(gè)類的字節(jié)碼文件,不重啟服務(wù)器。
方案:asm/javaassist + agent+Instrumentation
1.字節(jié)碼修改框架有很多第三方的字節(jié)碼修改框架,由于前期接觸了apm 產(chǎn)品pinpoint,所以決定使用asm/javaassist 框架,相對(duì)而言javaasist更為簡(jiǎn)單,但是效率較低。
ASM框架概述:
ASM有兩種處理字節(jié)碼的API分別是:
The ASM library provides two APIs for generating and transforming compiled
classes: the core API provides an event based representation of classes, while
the tree API provides an object based representation.
可以類比解析xml
These two APIs can be compared to the Simple API for XML (SAX) and
Document Object Model (DOM) APIs for XML documents: the event based
API is similar to SAX, while the object based API is similar to DOM. The
object based API is built on top of the event based one, like DOM can be
provided on top of SAX.
ASM字節(jié)碼修改demo:
github:https://github.com/chengbingh...
ASM 十分底層,比如我們要生成一個(gè)包含幾個(gè)熟悉和一個(gè)方法的接口,其代碼如下:
public static void main(String[] args) throws IOException { ClassWriter cw = new ClassWriter(0); cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT + Opcodes.ACC_INTERFACE, "com/hcb/asm/generate1/Comparable", null, "java/lang/Object", new String[]{"com/hcb/asm/generate123"}); cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "LESS", "I", null, new Integer(0)).visitEnd(); cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "EQUAL", "I", null, new Integer(1)).visitEnd(); cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, "GREATER", "I", null, new Integer(2)).visitEnd(); cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "compareTo", "(Ljava/lang/Object;)I", null, null).visitEnd(); cw.visitEnd(); byte[] b = null; b = cw.toByteArray(); //將上述生成的byts 寫入一個(gè)XX.class 文件中,再通過(guò)一個(gè)反編譯軟件就可以看到生成的類。 File file = new File("Comparable1.class"); FileOutputStream fos = new FileOutputStream(file); fos.write(b); fos.close(); }
如果操作不當(dāng)會(huì)產(chǎn)生一些奇怪的字節(jié)碼,比如下面的這個(gè)類,其方法和屬性都重復(fù)了:
javaasist框架demo:
github:https://github.com/chengbingh...
上述demo展示了如何使用javaassist修改字節(jié)碼.
**
2. agent說(shuō)明java 提供了agent可以用來(lái)修改字節(jié)碼,有兩個(gè)修改時(shí)機(jī),一個(gè)是class文件加載進(jìn)虛擬機(jī)時(shí),一個(gè)是在runtime。
可以通過(guò)參數(shù):-javaagent 指定agent jar 包位置,其實(shí)在jdk 中有一個(gè)示例jar,以jdk1.8為例,在JRE_HOEM/lib/management-agent.jar
這是一個(gè)空的jar包,但是其中有manifest.mf的寫法。
Premain-Class: 對(duì)應(yīng)是在加載進(jìn)jvm時(shí)。
我們以pingpoint1.7.1為參考:
pinpoint的agent 指定的一個(gè)啟動(dòng)參數(shù)是:
-javaagent:C:/kingdee/tomcat/apache-tomcat-8.0.48_ppagent/agent-hcb/pinpoint-bootstrap-1.7.1.jar
我們注意到premain-class指定的class有一個(gè)方法premain,這個(gè)方法即入口函數(shù)
Agent-Class:對(duì)應(yīng)運(yùn)行時(shí)。
3.運(yùn)行時(shí)修改字節(jié)碼案例github:地址:
修改工程:https://github.com/chengbingh...
測(cè)試工程:https://github.com/chengbingh...
UpdateClazz的main函數(shù)中根據(jù)某虛擬機(jī)的pid將agent 的jar包load到agent.
agent jar 包的manifest 文件中指定了agentMain方法所在的類
AgentMain 的agentMain方法中調(diào)用Transformer修改修改字節(jié)碼,案例中使用javaasist修改字節(jié)碼。
測(cè)試步驟是:
訪問(wèn)啟動(dòng)tomcat訪問(wèn)對(duì)于servlet
UpdateClazz修改字節(jié)碼(可以用jps命令獲取pid)
再次訪問(wèn)
發(fā)現(xiàn)已經(jīng)修改
相關(guān)微信公眾號(hào):
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69701.html
摘要:實(shí)際上并未引入太多新特性,不過(guò)有一個(gè)新特性最引人注目等了這么久終于支持類型推斷了,那么今天就來(lái)看一看的類型推斷,和其他語(yǔ)言相比有哪些異同吧。本次更新也支持了類型推斷,對(duì)于這種重量級(jí)語(yǔ)言來(lái)說(shuō)還是一件值得高興的事。 0x01 Java 10簡(jiǎn)介 自從有了校內(nèi)的下載網(wǎng)站,很少上Oracle官網(wǎng)下載JDK了,結(jié)果前兩天聽鐘神說(shuō)Java 10都出來(lái)了2333。干IT這行還真是要與時(shí)俱進(jìn)啊,那就...
摘要:下面是異常處理機(jī)制的語(yǔ)法結(jié)構(gòu)業(yè)務(wù)實(shí)現(xiàn)代碼輸入不合法如果執(zhí)行塊里業(yè)務(wù)邏輯代碼時(shí)出現(xiàn)異常,系統(tǒng)自動(dòng)生成一個(gè)異常對(duì)象,該對(duì)象被提交給運(yùn)行時(shí)環(huán)境,這個(gè)過(guò)程被稱為拋出異常。 Java的異常機(jī)制主要依賴于try、catch、finally、throw和throws五個(gè)關(guān)鍵字, try關(guān)鍵字后緊跟一個(gè)花括號(hào)括起來(lái)的代碼塊(花括號(hào)不可省略),簡(jiǎn)稱try塊,它里面放置可能引發(fā)異常的代碼 catch后對(duì)...
閱讀 3706·2021-09-30 09:59
閱讀 2373·2021-09-13 10:34
閱讀 590·2019-08-30 12:58
閱讀 1522·2019-08-29 18:42
閱讀 2215·2019-08-26 13:44
閱讀 2936·2019-08-23 18:12
閱讀 3332·2019-08-23 15:10
閱讀 1637·2019-08-23 14:37