Java 字節(jié)碼增強技術 2019-02-01

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

1. 字節(jié)碼增強技術的應用場景:

????寫日志、事務管理

????常見的字節(jié)碼增強技術:

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

? ? ????Java Proxy API 通過invoke方法攔截出來相應的代碼邏輯。Proxy 是面向接口的,被代理的Class的所有方法調用都會通過反射調用invoke方法。

????????缺點:性能開銷大

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

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

? ? ? ? 缺點:不適合處理靈活的代碼邏輯

? ? ? ? Instrumentation API 不僅可以做字節(jié)碼增強,還可以通過調用getObjectSize(Object o) 方法來計算一個對象的精確大小。

? ? 3. ASM?

? ? ? ? ASM 是一個提供字節(jié)碼解析和操作的框架。CGlib 框架是基于ASM 實現(xiàn),而常用的框架Hibernate、Spring 是基于CGlib 實現(xiàn) AOP的。

? ? ? ? ASM 對使用者屏蔽了整個類的字節(jié)碼的長度、偏移量,能夠靈活、方便地解析和操作字節(jié)碼。主要提供 Core API 和Tree API。

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

? ? ? ? ? ? ClassVisitor、ClassAdapter、ClassReader、ClassWriter

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

? ? ? ? 工具類:

? ? ? ? ? ? TraceClassVisitor、CheckClassAdapter、ASMifier、Type

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

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


2. 兩種實現(xiàn)機制:

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

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

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

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

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

4. 使用較多的開源的字節(jié)碼增強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é)碼本身的工具庫,它實現(xiàn)的抽象層次是很低的,幾乎接近于指令級別。例子中的操作都是基于指令和操作數(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 指令將一個常量加載到操作數(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);


?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

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

友情鏈接更多精彩內容