JavaShuo
欄目
標籤
java asm 框架 淺析
時間 2019-11-07
標籤
java
asm
框架
淺析
欄目
Java
简体版
原文
原文鏈接
什麼是asm呢?asm是assembly的縮寫,是彙編的稱號,對於java而言,asm就是字節碼級別的編程。
而這裏說到的asm是指objectweb asm,一種.class的代碼生成器的開源項目.
ASM是一套java字節碼生成架構,它能夠動態生成二進制格式的stub類或其它代理類,
或者在類被java虛擬機裝入內存以前,動態修改類。
如今挺多流行的框架都使用到了asm.因此從aop追溯來到了這。
1.什麼是ObjectWeb ASM
ObjectWeb ASM是輕量級的Java字節碼處理框架。它能夠動態生成二進制格式的stub類或其餘代理類,或者在類被JAVA虛擬機裝入內存以前,動態修改類。
ASM 提供了與 BCEL和SERP類似的功能,只有22K的大小,比起350K的BCEL和150K的SERP來講,是至關小巧的,而且它有更高的執行效率,
是BCEL 的7倍,SERP的11倍以上。
在我看來,ObjectWeb ASM具備以下幾個很是誘人的特色
* 小巧、高效
* 源代碼實現很是簡潔而又優雅,簡直就是Gof的《設計模式》很是棒的註解
* 字節碼級的控制,可以更高效地實現字節碼的控制
ObjectWeb ASM有2組接口:
* 基於事件驅動的接口,相似於xml的SAX接口,visitor模式,在訪問到類定義某個部分的時候進行回調,實現上比tree接口高效,佔用內存更小
* 基於tree的接口,相似於xml的DOM接口,將類定義解析成tree
這裏咱們將使用ObjectWeb ASM的事件驅動接口
2. 目標
咱們將對已有的字節碼進行加強,收集進入方法和退出方法的信息,這裏主要解決Method Monitor的字節碼加強部分,
不對收集後的數據處理作更深刻地研究,出於演示的目的,咱們定義了以下的收集方法的訪問信息處理,
在實際應用中,咱們可能會使用更好的格式收集更多的數據、使用異步處理提升性能、使用批量處理提升處理能力、使用友好的UI顯示信息等等,
此處不對這部分進行探討
1. package blackstar.methodmonitor.instrutment.monitor;
2. public class MonitorUtil
3. {
4. public final static String CLASS_NAME = MonitorUtil.class.getName()
5. .replaceAll("\\.", "/");
6. public final static String ENTRY_METHOD = "entryMethod";
7. public final static String EXIT_METHOD = "exitMethod";
8. public final static String METHOD = "(Ljava/lang/String;Ljava/lang/String;)V";
9.
10. public static void entryMethod(String className, String methodName)
11. {
12. System.out.println("entry : " + className + "." + methodName);
13. }
14.
15. public static void exitMethod(String className, String methodName)
16. {
17. System.out.println("exit : " + className + "." + methodName);
18. }
19. }
3. 從字節碼開始
實際上,對於被監控制的代碼,咱們所須要實現的功能以下,紅色部分的代碼是咱們須要在動態期插到字節碼中間的
public xxx method(…)
{
try
{
methodEntry(…)
methodCode
}
finally
{
methodExit(…)
}
}
這個問題看起來簡單,實際則沒有那麼容易,由於在JVM的字節碼設計中,字節碼並不直接支持finally語句,而是使用try…catch來模擬的,咱們先來看一個例子
Java代碼
1. package blackstar.methodmonitor.instrutment.test;
2.
3. public class Test
4. {
5. public void sayHello() throws Exception
6. {
7. try
8. {
9. System.out.println("hi");
10. } catch (Exception e)
11. {
12. System.out.println("exception");
13. return;
14. } finally
15. {
16. System.out.println("finally");
17. }
18. }
19. }
咱們看看字節碼是如何處理finally語句的
首先看看異常表,異常是在JVM級別上直接支持的,下面異常表的意思是,在執行0-8語句的時候,若是有異常java.lang.Exception拋出,則進入第11語句,
在執行0-20語句的時候,有任何異常拋出,都進入29語句。實際上JVM是這樣實現finally語句的:
* 在任何return語句以前,都會增長finally語句中的字節碼
* 定義一個捕獲全部異常的語句,增長finally語句中的字節碼,若是finally中沒有return語句,則會將異常再次拋出去(處理方法以拋出異常的方式結束)
Exceptions:
[0-8): 11 - java.lang.Exception
[0-20): 29
咱們再看看字節碼具體是如何作的
0 getstatic java.lang.System.out
3 ldc "hi" (java.lang.String)
5 invokevirtual println
8 goto 40
// System.out.println("hi");,執行完以後執行返回(goto 40)
11 astore_1
12 getstatic java.lang.System.out
15 ldc "exception" (java.lang.String)
17 invokevirtual println
// System.out.println("exception");
20 getstatic java.lang.System.out
23 ldc "finally" (java.lang.String)
25 invokevirtual println
// return語句以前插入finally部分字節碼
// System.out.println("finally");
28 return
29 astore_2
30 getstatic java.lang.System.out
33 ldc "finally" (java.lang.String)
35 invokevirtual println
38 aload_2
39 athrow
//當在執行0-29語句中,若是有異常拋出,則執行這段finally語句
//此處的astore_2(將棧頂值——即exception的地址——設給第2個local變量)和aload_2(將第2個local變量的值入棧)這兩個字節碼實際是沒必要要的,
//但須要注意的是,若是這2段代碼去掉的話,要考慮增大操做棧(max stack)以容納這個exception地址
//System.out.println("finally");
40 getstatic java.lang.System.out
43 ldc "finally" (java.lang.String)
45 invokevirtual println
// return語句以前插入finally部分字節碼
// System.out.println("finally");
48 return
實際上,咱們須要作的就是
* 在方法進入時插入方法進入代碼(須要注意,對於構造函數不容許作這種處理,構造函數第一步必須調用父類的構造函數。
* 在每一個return操做(包括return、ireturn、freturn等)以前,插入方法退出代碼
* 定義一個捕獲全部異常的處理,在處理中,插入方法退出代碼(即方法以拋異常的方式終止執行)
4. 實現
咱們看看使用ObjectWeb ASM如何實現咱們上面描述的功能
1)ObjectWeb ASM的字節碼修改
1. ClassReader cr = new ClassReader(byteArray); //使用字節碼構監一個reader
2. ClassWriter cw = new ClassWriter(cr, 0);//writer將基於已有的字節碼進行修改
3. MonitorClassVisitor ca = new MonitorClassVisitor(cw);//修改處理回調類
4. cr.accept(ca, 0);
相關文章
1.
Java字節碼框架ASM
2.
Java中ASM框架詳解
3.
Java 集合框架淺析
4.
【Java】淺析SSH框架
5.
Java——集合框架(淺析)
6.
淺析IoC框架
7.
Backbone框架淺析
8.
LitePal框架淺析
9.
淺析Dubbo框架
10.
Java字節碼修改框架ASM
更多相關文章...
•
Java Spring框架是什麼?它有哪些好處?
-
Spring教程
•
SQLite - Java
-
SQLite教程
•
Java 8 Stream 教程
•
互聯網組織的未來:剖析GitHub員工的任性之源
相關標籤/搜索
java框架
淺析
asm
框架
JAVA集合框架
java通訊框架
J2EE淺析
源碼淺析
淺淺
Java
MyBatis教程
Hibernate教程
Spring教程
java
架構
Java 8
0
分享到微博
分享到微信
分享到QQ
每日一句
每一个你不满意的现在,都有一个你没有努力的曾经。
最新文章
1.
安裝cuda+cuDNN
2.
GitHub的使用說明
3.
phpDocumentor使用教程【安裝PHPDocumentor】
4.
yarn run build報錯Component is not found in path 「npm/taro-ui/dist/weapp/components/rate/index「
5.
精講Haproxy搭建Web集羣
6.
安全測試基礎之MySQL
7.
C/C++編程筆記:C語言中的複雜聲明分析,用實例帶你完全讀懂
8.
Python3教程(1)----搭建Python環境
9.
李宏毅機器學習課程筆記2:Classification、Logistic Regression、Brief Introduction of Deep Learning
10.
阿里雲ECS配置速記
本站公眾號
歡迎關注本站公眾號,獲取更多信息
相關文章
1.
Java字節碼框架ASM
2.
Java中ASM框架詳解
3.
Java 集合框架淺析
4.
【Java】淺析SSH框架
5.
Java——集合框架(淺析)
6.
淺析IoC框架
7.
Backbone框架淺析
8.
LitePal框架淺析
9.
淺析Dubbo框架
10.
Java字節碼修改框架ASM
>>更多相關文章<<