1. 程式人生 > >java如何檢視jvm中動態代理class類內容

java如何檢視jvm中動態代理class類內容

在看dubbo原始碼時,發現dubbo呼叫過程設計到了很多動態代理類技術,但是這些動態代理類都是執行在記憶體中的,沒有生成class檔案,不瞭解到這些動態代理類的內容,就不知道他的呼叫過程是什麼?

下面例子中是我對mybatis框架的除錯,我們都知道mybatis框架操作資料庫需要寫mapper.xml和mapper.java介面,持久層實現類可直接注入mapper.java類並進行呼叫方法操作資料庫,mybatis它是如何將mapper.java介面類進行包裝供呼叫的呢?

主要工具:jvm的HSDB工具

作業系統:windows系統

jdk版本:jdk1.8

1、斷點

dubug模式下,代理物件上下斷點,這一步主要是方便獲取代理類的類名,大家直接打印出來也可以。斷點操作是防止代理類會變。

System.out.println("***&&&&&&&&&&&"+userMapper.getClass().getName());

2、檢視程序ID

jps命令檢視當前程式的程序ID值,注意程式如果有重啟,程序id是會變的。

那如果確定程序id呢?很簡單,在專案未啟動時,jps看下,專案啟動後,jps看下,多了那個程序id就是我們需要的id值了。

我當前程式啟動程序是38916。

3、啟動jvm中HSDB工具

hsdb是jvm自帶的工具,所以前提要把jdk安裝好,環境配置好。

java -classpath "%JAVA_HOME%/lib/sa-jdi.jar" sun.jvm.hotspot.HSDB

4、配置HSDB

點選【File】-->【Attach to hotspot process】-->輸入程序id-->【ok】

5、獲取代理物件類名

我斷點userMapper對應代理類的類名是$Proxy18@4954。圖片中顯示的很明顯。

6、根據代理類類名在JVM中檢視class

點選【Tools】-->【Class Browser】-->輸入代理類類名

這裡userMapper物件顯示代理類類名是$Proxy18,下面查找出來一個。

7、生成class

點選查找出來的class,再點選【Create .class File】,此操作會在本地生成一個class檔案。

8、class反編譯

預設生成的class檔案在c盤,我的目錄是在C:\Users\Lu\com\sun\proxy\$Proxy18.class,仔細看下,生成路徑它是根據包名生成相應的目錄。

jd-gui.exe反編譯工具編譯不成功。

我是直接將class檔案copy到idea工具,某個專案的target/class目錄下,讓idea工具反編譯。看到selectByNumb方法了,說明這個類正是我要找userMapper的代理類。

 

通過這次反編譯結果,可以明白:

1、為什麼Proxy.newProxyInstance生成代理類時,要傳入InvocationHandler類,是如何調到invoke()方法的。因為代理物件對方法的實現是直接呼叫handler.invoke方法的。

2、為什麼mybatis寫的mapper.java介面類,可以直接注入並呼叫,因為mybatis對每個mapper.java介面類,生成了代理物件是實現