Java 字節(jié)碼增強(qiáng)技術(shù) 2019-02-01

本文將介紹有哪些常見的字節(jié)碼增強(qiáng)技術(shù)牧愁、字節(jié)碼增強(qiáng)的實(shí)現(xiàn)方式、AOP實(shí)現(xiàn)的原理。

1. 字節(jié)碼增強(qiáng)技術(shù)的應(yīng)用場景:

????寫日志、事務(wù)管理

????常見的字節(jié)碼增強(qiáng)技術(shù):

????1. Java 動(dòng)態(tài)代理

? ? ????Java Proxy API 通過invoke方法攔截出來相應(yīng)的代碼邏輯涮俄。Proxy 是面向接口的撮竿,被代理的Class的所有方法調(diào)用都會(huì)通過反射調(diào)用invoke方法拥峦。

????????缺點(diǎn):性能開銷大

????2.? Java 5 提供的Instrumentation API

? ? ? ? 適應(yīng)場景:適用于監(jiān)控

? ? ? ? 缺點(diǎn):不適合處理靈活的代碼邏輯

? ? ? ? Instrumentation API 不僅可以做字節(jié)碼增強(qiáng)麸恍,還可以通過調(diào)用getObjectSize(Object o) 方法來計(jì)算一個(gè)對(duì)象的精確大小。

? ? 3. ASM?

? ? ? ? ASM 是一個(gè)提供字節(jié)碼解析和操作的框架拼弃。CGlib 框架是基于ASM 實(shí)現(xiàn)夏伊,而常用的框架Hibernate、Spring 是基于CGlib 實(shí)現(xiàn) AOP的吻氧。

? ? ? ? ASM 對(duì)使用者屏蔽了整個(gè)類的字節(jié)碼的長度溺忧、偏移量咏连,能夠靈活、方便地解析和操作字節(jié)碼鲁森。主要提供 Core API 和Tree API祟滴。

? ? ? ? Core API 主要的類(接口):

? ? ? ? ? ? ClassVisitor、ClassAdapter歌溉、ClassReader垄懂、ClassWriter

? ? ? ? Tree API 主要的類(接口):

? ? ? ? 工具類:

? ? ? ? ? ? TraceClassVisitor、CheckClassAdapter痛垛、ASMifier草慧、Type

? ? ? ? ? ? TraceClassVisitor 能打印ClassWriter 提供的byte[] 字節(jié)數(shù)組。

? ? ? ? ? ? TraceClassVisitor 通過初始化一個(gè)ClassWriter 和一個(gè)Printer 對(duì)象來打印我們需要的字節(jié)流信息匙头。方便比較類文件及分析字節(jié)碼文件的結(jié)構(gòu)漫谷。


2. 兩種實(shí)現(xiàn)機(jī)制:

? ? (1) 通過創(chuàng)建原始類的一個(gè)子類(動(dòng)態(tài)創(chuàng)建的類繼承原來的類)。子類名以原始類名為前綴蹂析,以避免重名舔示。Spring AOP 使用的就是這種

? ? (2) 直接修改原始類的字節(jié)碼。類的跟蹤過程中使用

3. 實(shí)現(xiàn)字節(jié)碼增強(qiáng)要執(zhí)行兩個(gè)步驟:

? ? (1) 在內(nèi)存中獲取到原始的字節(jié)碼识窿, 然后通過一些開源的API 來修改它的byte[] 數(shù)組斩郎,得到一個(gè)新的byte[] 數(shù)組。

? ? (2) 將新的byte[] 數(shù)組加載到PermGen 區(qū)(即加載新的byte[] 數(shù)組或替換原始類的字節(jié)碼)喻频。

4. 使用較多的開源的字節(jié)碼增強(qiáng)API:

? ? ASM、javassist肘迎、BCEL甥温、SERP、CGLib(基于ASM )

5. 加載字節(jié)數(shù)組的方式:

????1. 基于Java 的instrument API (接口ClassFileTransformer 的transform方法)

byte[] transform( ClassLoader loader, String className, Class?classBeingRedefined, ProtectionDomain ????protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException

????2. 通過指定的ClassLoader? 來完成

????FAQ: 這兩種加載字節(jié)數(shù)組的方式的區(qū)別妓布?

附錄:

????ASM? 是一種修改字節(jié)碼本身的工具庫姻蚓,它實(shí)現(xiàn)的抽象層次是很低的,幾乎接近于指令級(jí)別匣沼。例子中的操作都是基于指令和操作數(shù)的狰挡。

/**

* Visits a local variable instruction. A local variable instruction is an

* instruction that loads or stores the value of a local variable.

*

* @param opcode the opcode of the local variable instruction to be visited.

*? ? ? ? This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE,

*? ? ? ? LSTORE, FSTORE, DSTORE, ASTORE or RET.

* @param var the operand of the instruction to be visited. This operand is

*? ? ? ? the index of a local variable.

*/

void visitVarInsn(int opcode,int var);

LDC 指令將一個(gè)常量加載到操作數(shù)棧

/**

* Visits a LDC instruction.

*

* @param cst the constant to be loaded on the stack. This parameter must be

*? ? ? ? a non null {@link Integer}, a {@link Float}, a {@link Long}, a

*? ? ? ? {@link Double} a {@link String} (or a {@link Type} for

*? ? ? ? <tt>.class</tt>constants, for classes whose version is 49.0 or

*? ? ? ? more).

*/

void visitLdcInsn(Object cst);


/**

* Visits a field instruction. A field instruction is an instruction that

* loads or stores the value of a field of an object.

*

* @param opcode the opcode of the type instruction to be visited. This

*? ? ? ? opcode is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.

* @param owner the internal name of the field's owner class (see {@link

*? ? ? ? Type#getInternalName() getInternalName}).

* @param name the field's name.

* @param desc the field's descriptor (see {@link Type Type}).

*/

void visitFieldInsn(int opcode, String owner, String name, String desc);



/**

* Visits a method instruction. A method instruction is an instruction that

* invokes a method.

*

* @param opcode the opcode of the type instruction to be visited. This

*? ? ? ? opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC,

*? ? ? ? INVOKEINTERFACE or INVOKEDYNAMIC.

* @param owner the internal name of the method's owner class (see {@link

*? ? ? ? Type#getInternalName() getInternalName})

*? ? ? ? or {@link org.objectweb.asm.Opcodes#INVOKEDYNAMIC_OWNER}.

* @param name the method's name.

* @param desc the method's descriptor (see {@link Type Type}).

*/

void visitMethodInsn(int opcode, String owner, String name, String desc);


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市释涛,隨后出現(xiàn)的幾起案子加叁,更是在濱河造成了極大的恐慌,老刑警劉巖唇撬,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件它匕,死亡現(xiàn)場離奇詭異,居然都是意外死亡窖认,警方通過查閱死者的電腦和手機(jī)豫柬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門告希,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人烧给,你說我怎么就攤上這事燕偶。” “怎么了础嫡?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵杭跪,是天一觀的道長。 經(jīng)常有香客問我驰吓,道長涧尿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任檬贰,我火速辦了婚禮姑廉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘翁涤。我一直安慰自己桥言,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布葵礼。 她就那樣靜靜地躺著号阿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鸳粉。 梳的紋絲不亂的頭發(fā)上扔涧,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天,我揣著相機(jī)與錄音届谈,去河邊找鬼枯夜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛艰山,可吹牛的內(nèi)容都是我干的湖雹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼曙搬,長吁一口氣:“原來是場噩夢啊……” “哼摔吏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起纵装,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤征讲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后搂擦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體稳诚,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年瀑踢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扳还。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片才避。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖氨距,靈堂內(nèi)的尸體忽然破棺而出桑逝,到底是詐尸還是另有隱情,我是刑警寧澤俏让,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布楞遏,位于F島的核電站,受9級(jí)特大地震影響首昔,放射性物質(zhì)發(fā)生泄漏寡喝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一勒奇、第九天 我趴在偏房一處隱蔽的房頂上張望预鬓。 院中可真熱鬧,春花似錦赊颠、人聲如沸格二。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽顶猜。三九已至,卻和暖如春痘括,著一層夾襖步出監(jiān)牢的瞬間长窄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國打工远寸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抄淑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓驰后,卻偏偏與公主長得像,于是被迫代替她去往敵國和親矗愧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子灶芝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容

  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說明:當(dāng)在唯一索引所對(duì)應(yīng)的列上鍵入重復(fù)值時(shí),會(huì)觸發(fā)此異常唉韭。 O...
    我想起個(gè)好名字閱讀 5,338評(píng)論 0 9
  • Overview The ccxt library is a collection of available cr...
    郭蟈兒蟈兒閱讀 3,743評(píng)論 0 1
  • 到葡萄酒學(xué)院去學(xué)習(xí)釀酒夜涕,把葡萄變成酒的過程研究透,我們便有可能學(xué)會(huì)如何釀造一款好酒属愤。但若想釀造出偉大的酒女器,則以下五...
    酒公子閱讀 278評(píng)論 0 0
  • 你在哪里 讓我千萬次尋找 懷念你的味道 你的音容笑貌 媽媽說 你在孩子身上的一針一線里 老師說 你在浩瀚的知識(shí)里 ...
    絲雨飄飛閱讀 144評(píng)論 0 1