摘要:運行時修改字節(jié)碼需求在運行時動態(tài)修改某個類的字節(jié)碼文件,不重啟服務器。方案字節(jié)碼修改框架有很多第三方的字節(jié)碼修改框架,由于前期接觸了產品所以決定使用框架,相對而言更為簡單,但是效率較低。
運行時修改字節(jié)碼
需求:在運行時動態(tài)修改某個類的字節(jié)碼文件,不重啟服務器。
方案:asm/javaassist + agent+Instrumentation
1.字節(jié)碼修改框架有很多第三方的字節(jié)碼修改框架,由于前期接觸了apm 產品pinpoint,所以決定使用asm/javaassist 框架,相對而言javaasist更為簡單,但是效率較低。
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 十分底層,比如我們要生成一個包含幾個熟悉和一個方法的接口,其代碼如下:
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 寫入一個XX.class 文件中,再通過一個反編譯軟件就可以看到生成的類。 File file = new File("Comparable1.class"); FileOutputStream fos = new FileOutputStream(file); fos.write(b); fos.close(); }
如果操作不當會產生一些奇怪的字節(jié)碼,比如下面的這個類,其方法和屬性都重復了:
javaasist框架demo:
github:https://github.com/chengbingh...
上述demo展示了如何使用javaassist修改字節(jié)碼.
**
2. agent說明java 提供了agent可以用來修改字節(jié)碼,有兩個修改時機,一個是class文件加載進虛擬機時,一個是在runtime。
可以通過參數:-javaagent 指定agent jar 包位置,其實在jdk 中有一個示例jar,以jdk1.8為例,在JRE_HOEM/lib/management-agent.jar
這是一個空的jar包,但是其中有manifest.mf的寫法。
Premain-Class: 對應是在加載進jvm時。
我們以pingpoint1.7.1為參考:
pinpoint的agent 指定的一個啟動參數是:
-javaagent:C:/kingdee/tomcat/apache-tomcat-8.0.48_ppagent/agent-hcb/pinpoint-bootstrap-1.7.1.jar
我們注意到premain-class指定的class有一個方法premain,這個方法即入口函數
Agent-Class:對應運行時。
3.運行時修改字節(jié)碼案例github:地址:
修改工程:https://github.com/chengbingh...
測試工程:https://github.com/chengbingh...
UpdateClazz的main函數中根據某虛擬機的pid將agent 的jar包load到agent.
agent jar 包的manifest 文件中指定了agentMain方法所在的類
AgentMain 的agentMain方法中調用Transformer修改修改字節(jié)碼,案例中使用javaasist修改字節(jié)碼。
測試步驟是:
訪問啟動tomcat訪問對于servlet
UpdateClazz修改字節(jié)碼(可以用jps命令獲取pid)
再次訪問
發(fā)現已經修改
相關微信公眾號:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69701.html
摘要:實際上并未引入太多新特性,不過有一個新特性最引人注目等了這么久終于支持類型推斷了,那么今天就來看一看的類型推斷,和其他語言相比有哪些異同吧。本次更新也支持了類型推斷,對于這種重量級語言來說還是一件值得高興的事。 0x01 Java 10簡介 自從有了校內的下載網站,很少上Oracle官網下載JDK了,結果前兩天聽鐘神說Java 10都出來了2333。干IT這行還真是要與時俱進啊,那就...
閱讀 3621·2021-09-30 09:59
閱讀 2229·2021-09-13 10:34
閱讀 577·2019-08-30 12:58
閱讀 1507·2019-08-29 18:42
閱讀 2198·2019-08-26 13:44
閱讀 2922·2019-08-23 18:12
閱讀 3321·2019-08-23 15:10
閱讀 1625·2019-08-23 14:37