歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java6 的類反射瓶頸

用native code就不說了, 當調用次數達到一定的閥值的時候,sun jdk 會使用

MethodAccessorGenerator.generate 生成一個虛擬的class, GeneratedMethodAccessor1,2...之類

你可以在啟動參數裡 使用  XX:+TraceClassLoading, 可以看到 load 的虛擬的class

從理論上來說,這樣的調用等於是生成新的class,直接調用具體的類的方法,性能應該和直接調用的方法接近,或者類似,除了方法調用的入棧和出棧,當然當用hotspot編譯運行的時候的,內聯可以解決這樣的問題。

結果卻讓人吃驚

在用類反射調用的時候100萬次需要3秒,而直接調用卻只要10毫秒。

有人說,因為是method的調用,涉及到method的quickCheckMemberAccess,ensureMemberAccess檢查,這個你可以通過設置method.setAccessor(true) 繞過成員檢查。

主要的原因是: 因為接口的通用性,java 的invoke 方法 是傳object, 和object[] 數組的。

也就是如果是簡單類型的話,在接口處必須封裝成object, 例如 long ,在javac compile的時候 用了Long.valueOf() 轉型

那也就是大量了生成了Long 的object, 同時 傳入的參數是Object[]數值,那還需要額外封裝object數組。

在調用的時候,產生了額外的不必要的內存浪費,當調用次數達到一定量的時候,最終還導致了GC。

接口的通用性在對性能要求不高的系統裡通用性非常高,但在對性能要求高的系統裡簡直就是災難。

Copyright © Linux教程網 All Rights Reserved