Java字節(jié)碼的增強(qiáng)技術(shù)
Java字節(jié)碼的增強(qiáng)技術(shù)
一、簡(jiǎn)單介紹下幾種java字節(jié)碼增強(qiáng)技術(shù)
1、ASM
ASM是一個(gè)Java字節(jié)碼操控框架,它能被用來動(dòng)態(tài)生成類或者增強(qiáng)既有類的功能。ASM可以直接產(chǎn)生class文件,也可以在類被加載入Java虛擬機(jī)之前動(dòng)態(tài)改變類行為。ASM從類文件中讀入信息后,能夠改變類行為,分析類信息,甚至能夠根據(jù)用戶要求生成新類。
ASM框架中的核心類有以下幾個(gè):
?、?nbsp; ClassReader:該類用來解析編譯過的class字節(jié)碼文件。
?、?nbsp; ClassWriter:該類用來重新構(gòu)建編譯后的類,比如說修改類名、屬性以及方法,甚至可以生成新的類的字節(jié)碼文件。
③ ClassAdapter:該類也實(shí)現(xiàn)了ClassVisitor接口,它將對(duì)它的方法調(diào)用委托給另一個(gè)ClassVisitor對(duì)象。
參考代碼:
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 {
//生成一個(gè)類只需要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();
}
}
2、Javassist
Javassist是一個(gè)開源的分析、編輯和創(chuàng)建Java字節(jié)碼的類庫。
它已加入了開放源代碼JBoss應(yīng)用服務(wù)器項(xiàng)目,通過使用Javassist對(duì)字節(jié)碼操作為JBoss實(shí)現(xiàn)動(dòng)態(tài)"AOP"框架。
利用Javassist實(shí)現(xiàn)字節(jié)碼增強(qiáng)時(shí),可以無須關(guān)注字節(jié)碼刻板的結(jié)構(gòu),其優(yōu)點(diǎn)就在于編程簡(jiǎn)單。直接使用java編碼的形式,而不需要了解虛擬機(jī)指令,就能動(dòng)態(tài)改變類的結(jié)構(gòu)或者動(dòng)態(tài)生成類。其中最重要的是ClassPool、CtClass、CtMethod、CtField這四個(gè)類:
- CtClass(compile-time class):編譯時(shí)類信息,它是一個(gè)class文件在代碼中的抽象表現(xiàn)形式,可以通過一個(gè)類的全限定名來獲取一個(gè)CtClass對(duì)象,用來表示這個(gè)類文件。
- ClassPool:從開發(fā)視角來看,ClassPool是一張保存CtClass信息的HashTable,key為類名,value為類名對(duì)應(yīng)的CtClass對(duì)象。當(dāng)我們需要對(duì)某個(gè)類進(jìn)行修改時(shí),就是通過pool.getCtClass(“className”)方法從pool中獲取到相應(yīng)的CtClass。
- CtMethod、CtField:這兩個(gè)比較好理解,對(duì)應(yīng)的是類中的方法和屬性。
參考代碼:
import javassist.*;
public class CreatePerson {
public static void createPseson() throws Exception {
ClassPool pool = ClassPool.getDefault();
// 1. 創(chuàng)建一個(gè)空類
CtClass cc = pool.makeClass("com.test.javassist.Person");
// 2. 新增一個(gè)字段 private String name;
// 字段名為name
CtField param = new CtField(pool.get("java.lang.String"), "name", cc);
// 訪問級(jí)別是 private
param.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)建一個(gè)名為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);
//這里會(huì)將這個(gè)創(chuàng)建的類對(duì)象編譯為.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();
}
}
}
3、Byte Buddy
Byte Buddy是一個(gè)代碼生成和操作庫,用于在Java應(yīng)用程序運(yùn)行時(shí)創(chuàng)建和修改Java類,而無需編譯器的幫助。
除了Java類庫附帶的代碼生成實(shí)用程序外,Byte Buddy還允許創(chuàng)建任意類,并且不限于實(shí)現(xiàn)用于創(chuàng)建運(yùn)行時(shí)代理的接口。
此外,Byte Buddy提供了一種方便的API,可以使用Java代理或在構(gòu)建過程中手動(dòng)更改類。
參考代碼:
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!"));
4、JVM-SANDBOX
JVM沙箱容器,一種JVM的非侵入式運(yùn)行期AOP解決方案:
動(dòng)態(tài)增強(qiáng)類你所指定的類,獲取你想要的參數(shù)和行信息甚至改變方法執(zhí)行。
動(dòng)態(tài)可插拔容器框架。
到此這篇關(guān)于Java字節(jié)碼的增強(qiáng)技術(shù)的文章就介紹到這了,更多相關(guān)Java字節(jié)碼增強(qiáng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 學(xué)會(huì)Java字節(jié)碼指令,成為技術(shù)大佬
- Java之字節(jié)碼以及優(yōu)勢(shì)案例講解
- Java字節(jié)碼增強(qiáng)技術(shù)知識(shí)點(diǎn)詳解
- 詳解Java動(dòng)態(tài)字節(jié)碼技術(shù)
- 詳解Java字節(jié)碼編程之非常好用的javassist
- 淺談javap命令拆解字節(jié)碼文件
- Java字節(jié)碼中jvm實(shí)例用法
- Javassist如何操作Java 字節(jié)碼
- Java中invokedynamic字節(jié)碼指令問題
- java獲取版本號(hào)及字節(jié)碼編譯版本方法示例
- java 獲取字節(jié)碼文件的幾種方法總結(jié)
- java 中如何獲取字節(jié)碼文件的相關(guān)內(nèi)容
- java字節(jié)碼框架ASM操作字節(jié)碼的方法淺析
- java字節(jié)碼框架ASM的深入學(xué)習(xí)
- Java 將字符串動(dòng)態(tài)生成字節(jié)碼的實(shí)現(xiàn)方法
- 通過java字節(jié)碼分析學(xué)習(xí)對(duì)象初始化順序
相關(guān)文章
SpringBoot集成Tomcat服務(wù)架構(gòu)配置
這篇文章主要為大家介紹了SpringBoot集成Tomcat服務(wù)架構(gòu)配置,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
Spring?Boot?如何生成微信小程序短連接及發(fā)送短信在短信中打開小程序操作
最近遇到這樣的需求需要發(fā)送短信,通過短信中的短連接打開小程序操作,下面小編給大家分享Spring?Boot?如何生成微信小程序短連接發(fā)送短信在短信中打開小程序操作,感興趣的朋友跟隨小編一起看看吧2024-03-03
解決springboot啟動(dòng)成功,但訪問404的問題
這篇文章主要介紹了解決springboot啟動(dòng)成功,但訪問404的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
springboot 傳參校驗(yàn)@Valid及對(duì)其的異常捕獲方式
這篇文章主要介紹了springboot 傳參校驗(yàn)@Valid及對(duì)其的異常捕獲方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
深入解析java HashMap實(shí)現(xiàn)原理
這篇文章主要介紹了深入解析java HashMap實(shí)現(xiàn)原理的相關(guān)資料,需要的朋友可以參考下2015-09-09
SpringBoot實(shí)現(xiàn)國(guó)際化i18n詳解
國(guó)際化(Internationalization,簡(jiǎn)稱i18n)是指在軟件應(yīng)用中支持多種語言和文化的能力,本文將介紹如何在Spring?Boot應(yīng)用中實(shí)現(xiàn)國(guó)際化,需要的可以參考下2024-12-12
Spring-MVC異步請(qǐng)求之Servlet異步處理
這篇文章主要介紹了Spring-MVC異步請(qǐng)求之Servlet異步處理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01
老生常談Java網(wǎng)絡(luò)編程TCP通信(必看篇)
下面小編就為大家?guī)硪黄仙U凧ava網(wǎng)絡(luò)編程TCP通信(必看篇)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
Eclipse下編寫java程序突然不會(huì)自動(dòng)生成R.java文件和包的解決辦法
這篇文章主要介紹了Eclipse下編寫java程序突然不會(huì)自動(dòng)生成R.java文件和包的解決辦法 的相關(guān)資料,需要的朋友可以參考下2016-01-01

