av一区二区在线观看_亚洲男人的天堂网站_日韩亚洲视频_在线成人免费_欧美日韩精品免费观看视频_久草视

您的位置:首頁技術(shù)文章
文章詳情頁

Java字節(jié)碼增強(qiáng)技術(shù)知識點(diǎn)詳解

瀏覽:65日期:2023-02-09 14:25:33

簡單介紹下幾種java字節(jié)碼增強(qiáng)技術(shù)。

ASM

ASM是一個Java字節(jié)碼操控框架,它能被用來動態(tài)生成類或者增強(qiáng)既有類的功能。ASM可以直接產(chǎn)生class文件,也可以在類被加載入Java虛擬機(jī)之前動態(tài)改變類行為。ASM從類文件中讀入信息后,能夠改變類行為,分析類信息,甚至能夠根據(jù)用戶要求生成新類。

主頁:https://asm.ow2.io/index.html

ASM框架中的核心類有以下幾個:

① ClassReader:該類用來解析編譯過的class字節(jié)碼文件。

② ClassWriter:該類用來重新構(gòu)建編譯后的類,比如說修改類名、屬性以及方法,甚至可以生成新的類的字節(jié)碼文件。

③ ClassAdapter:該類也實(shí)現(xiàn)了ClassVisitor接口,它將對它的方法調(diào)用委托給另一個ClassVisitor對象。

參考代碼:

import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import org.objectweb.asm.ClassWriter;import org.objectweb.asm.Opcodes;public class GeneratorClass { public static void main(String[] args) throws IOException {//生成一個類只需要ClassWriter組件即可ClassWriter cw = new ClassWriter(0);//通過visit方法確定類的頭部信息cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC+Opcodes.ACC_ABSTRACT+Opcodes.ACC_INTERFACE,'com/asm3/Comparable', null, 'java/lang/Object', new String[]{'com/asm3/Mesurable'});//定義類的屬性cw.visitField(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL+Opcodes.ACC_STATIC,'LESS', 'I', null, new Integer(-1)).visitEnd();cw.visitField(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL+Opcodes.ACC_STATIC,'EQUAL', 'I', null, new Integer(0)).visitEnd();cw.visitField(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL+Opcodes.ACC_STATIC,'GREATER', 'I', null, new Integer(1)).visitEnd();//定義類的方法cw.visitMethod(Opcodes.ACC_PUBLIC+Opcodes.ACC_ABSTRACT, 'compareTo','(Ljava/lang/Object;)I', null, null).visitEnd();cw.visitEnd(); //使cw類已經(jīng)完成//將cw轉(zhuǎn)換成字節(jié)數(shù)組寫到文件里面去byte[] data = cw.toByteArray();File file = new File('D://Comparable.class');FileOutputStream fout = new FileOutputStream(file);fout.write(data);fout.close(); }}Javassist

Javassist是一個開源的分析、編輯和創(chuàng)建Java字節(jié)碼的類庫。

它已加入了開放源代碼JBoss應(yīng)用服務(wù)器項(xiàng)目,通過使用Javassist對字節(jié)碼操作為JBoss實(shí)現(xiàn)動態(tài)'AOP'框架。

主頁:http://www.javassist.org/

利用Javassist實(shí)現(xiàn)字節(jié)碼增強(qiáng)時,可以無須關(guān)注字節(jié)碼刻板的結(jié)構(gòu),其優(yōu)點(diǎn)就在于編程簡單。直接使用java編碼的形式,而不需要了解虛擬機(jī)指令,就能動態(tài)改變類的結(jié)構(gòu)或者動態(tài)生成類。其中最重要的是ClassPool、CtClass、CtMethod、CtField這四個類:

CtClass(compile-time class):編譯時類信息,它是一個class文件在代碼中的抽象表現(xiàn)形式,可以通過一個類的全限定名來獲取一個CtClass對象,用來表示這個類文件。

ClassPool:從開發(fā)視角來看,ClassPool是一張保存CtClass信息的HashTable,key為類名,value為類名對應(yīng)的CtClass對象。當(dāng)我們需要對某個類進(jìn)行修改時,就是通過pool.getCtClass(“className”)方法從pool中獲取到相應(yīng)的CtClass。

CtMethod、CtField:這兩個比較好理解,對應(yīng)的是類中的方法和屬性。

參考代碼:

import javassist.*;public class CreatePerson { public static void createPseson() throws Exception {ClassPool pool = ClassPool.getDefault();// 1. 創(chuàng)建一個空類CtClass cc = pool.makeClass('com.test.javassist.Person');// 2. 新增一個字段 private String name;// 字段名為nameCtField param = new CtField(pool.get('java.lang.String'), 'name', cc);// 訪問級別是 privateparam.setModifiers(Modifier.PRIVATE);// 初始值是 'xiaoming'cc.addField(param, CtField.Initializer.constant('xiaoming'));// 3. 生成 getter、setter 方法cc.addMethod(CtNewMethod.setter('setName', param));cc.addMethod(CtNewMethod.getter('getName', param));// 4. 添加無參的構(gòu)造函數(shù)CtConstructor cons = new CtConstructor(new CtClass[]{}, cc);cons.setBody('{name = 'xiaohong';}');cc.addConstructor(cons);// 5. 添加有參的構(gòu)造函數(shù)cons = new CtConstructor(new CtClass[]{pool.get('java.lang.String')}, cc);// $0=this / $1,$2,$3... 代表方法參數(shù)cons.setBody('{$0.name = $1;}');cc.addConstructor(cons);// 6. 創(chuàng)建一個名為printName方法,無參數(shù),無返回值,輸出name值CtMethod ctMethod = new CtMethod(CtClass.voidType, 'printName', new CtClass[]{}, cc);ctMethod.setModifiers(Modifier.PUBLIC);ctMethod.setBody('{System.out.println(name);}');cc.addMethod(ctMethod);//這里會將這個創(chuàng)建的類對象編譯為.class文件cc.writeFile('/Users/yangyue/workspace/springboot-learn/java-agent/src/main/java/'); } public static void main(String[] args) {try { createPseson();} catch (Exception e) { e.printStackTrace();} }}Byte Buddy

Byte Buddy是一個代碼生成和操作庫,用于在Java應(yīng)用程序運(yùn)行時創(chuàng)建和修改Java類,而無需編譯器的幫助。除了Java類庫附帶的代碼生成實(shí)用程序外,Byte Buddy還允許創(chuàng)建任意類,并且不限于實(shí)現(xiàn)用于創(chuàng)建運(yùn)行時代理的接口。此外,Byte Buddy提供了一種方便的API,可以使用Java代理或在構(gòu)建過程中手動更改類。

主頁:https://bytebuddy.net/

參考代碼:

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!'));JVM-SANDBOX

JVM沙箱容器,一種JVM的非侵入式運(yùn)行期AOP解決方案:

動態(tài)增強(qiáng)類你所指定的類,獲取你想要的參數(shù)和行信息甚至改變方法執(zhí)行。

動態(tài)可插拔容器框架。主頁:https://github.com/alibaba/jvm-sandbox

知識點(diǎn)擴(kuò)充:

動態(tài)生成字節(jié)碼

我們知道,我們編寫的 Java 代碼都是要被編譯成字節(jié)碼后才能放到 JVM 里執(zhí)行的,而字節(jié)碼一旦被加載到虛擬機(jī)中,就可以被解釋執(zhí)行。

字節(jié)碼文件(.class)就是普通的二進(jìn)制文件,它是通過 Java 編譯器生成的。而只要是文件就可以被改變,如果我們用特定的規(guī)則解析了原有的字節(jié)碼文件,對它進(jìn)行修改或者干脆重新定義,這不就可以改變代碼行為了么。

Java 生態(tài)里有很多可以動態(tài)生成字節(jié)碼的技術(shù),像 BCEL、Javassist、ASM、CGLib 等,它們各有自己的優(yōu)勢。有的使用復(fù)雜卻功能強(qiáng)大、有的簡單確也性能些差。

ASM 框架

ASM 是它們中最強(qiáng)大的一個,使用它可以動態(tài)修改類、方法,甚至可以重新定義類,連 CGLib 底層都是用 ASM 實(shí)現(xiàn)的。

當(dāng)然,它的使用門檻也很高,使用它需要對 Java 的字節(jié)碼文件有所了解,熟悉 JVM 的編譯指令。雖然我對 JVM 的字節(jié)碼語法不熟,但有大神開發(fā)了可以在 IDEA 里查看字節(jié)碼的插件:ASM Bytecode Outline,在要查看的類文件里右鍵選擇Show bytecode Outline即可以右側(cè)的工具欄查看我們要生成的字節(jié)碼。對照著示例,我們就可以很輕松地寫出操作字節(jié)碼的 Java 代碼了。

到此這篇關(guān)于Java字節(jié)碼增強(qiáng)技術(shù)知識點(diǎn)詳解的文章就介紹到這了,更多相關(guān)Java字節(jié)碼增強(qiáng)技術(shù)內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 国产在线播 | 成人av在线播放 | 久久综合婷婷 | 成人妇女免费播放久久久 | 久久久久久久成人 | 特黄一级 | 国产精品欧美一区喷水 | 精品精品视频 | 亚洲精品久久久久久一区二区 | 精品网 | 亚洲精品中文字幕 | 男女在线免费观看 | 欧美一级在线 | 深夜福利亚洲 | 久久99精品国产99久久6男男 | 狠狠狠色丁香婷婷综合久久五月 | 黄网站在线播放 | 日韩电影一区二区三区 | 欧美日韩亚洲一区 | 欧美日韩午夜精品 | 综合色播 | 成人一级黄色毛片 | 日韩一级| 国产综合在线视频 | 国产精品久久久久久久久久免费看 | 尤物在线精品视频 | 天天干天天操天天爽 | 99热这里只有精品8 激情毛片 | 亚洲永久| 91免费福利在线 | 国产精品免费在线 | 免费国产一区 | 亚洲国产小视频 | 久久精品亚洲成在人线av网址 | 日韩在线视频观看 | 久久99精品久久久久久国产越南 | 最新中文在线视频 | 亚洲精品免费观看 | 成人免费观看男女羞羞视频 | 中文字幕日韩一区二区 | www.成人在线视频 |