1. 程式人生 > >Java 反射呼叫的一種優化

Java 反射呼叫的一種優化

      寫一些Java框架的時候,經常需要通過反射get或者set某個bean的field,比較普通的做法是獲取field後呼叫java.lang.reflect.Field.get(Object),但每次都這樣呼叫,能否有優化的空間呢?

答案是有。

第一種:

      由於每次都是重複的呼叫,所以想到了快取每個bean的field,但這樣做還是不夠,所以想到了寫一個code generator。通過生成程式碼的方式,get或者set每個bean的時候直接呼叫該bean的getter或者setter,這個實現聽起來很牛逼,其實就是用asm生成一個類在用一個classloader載入進來每次呼叫直接invoke就可以了。

      可單純為了一個反射呼叫做這麼多,總感覺是大炮打了蚊子。

第二種:

      多謝@RednaxelaFX   的指點,找到了更簡單的做法:sun.misc.Unsafe

      使用也非常的簡單:首先通過sun.misc.Unsafe.objectFieldOffset(Field) 獲取field的offset,然後使用sun.misc.Unsafe.getObject(Object, long)獲取某個例項上的field的值。

      簡單的測試程式碼如下:

      通過測試發現,效率是普通java.lang.reflect.Field.get(Object)的3倍,當然,效能這個東西,還是自己測試了放心。

      這樣做有一個不好的地方:sun.misc.Unsafe在sun的包裡,預設情況下,eclipse編譯會報錯,在Window->Preference->Java->Compiler->Errors/Warnings->Deprecated and restricted API -> Forbidden Reference 修改成Warning或者Ignore就可以了。由於Unsafe在JDK中很多的類庫中都在使用,框架程式碼中使用還是很安全的,如果需要api變動,JDK原始碼的修改工作量比我們的大多了 :-0

      至於第一種方法,雖然麻煩,有時間還是可以嘗試一下的,有時間了寫一下。