編寫高級應用程序3

JIT編譯器是作爲一種依賴於平臺的本地庫提供的。如果JIT編譯器庫存在,則Java虛擬機將初始化Java本地接口(JNI)的本地代碼分支以調用在該庫中可獲得的JIT函數,而不是調用在解釋程序中的相應函數。


java.lang.Compiler 類被用來加載本地庫並啓動JIT編譯器內的初始化。當Java虛擬機調用一個Java方法時,它使用在加載的類對象的方法塊中所指定的調用(invoker)方法。Java虛擬機具有若干個調用者方法,例如,如果方法是同步的,或者它是一個本地方法,則將使用不同的調用者。JIT編譯器使用它自己的調用者。Sun的產品可以爲值ACC_MACHINE_COMPILED檢查方法存取位以告知解釋程序該方法的代碼已被編譯並存儲在加載類中。

  代碼何時成爲JIT編譯的代碼?


當一個方法被首次調用時,JIT編譯器爲該方法將方法塊編譯爲本地代碼,並將其存儲在該方法的代碼塊中。


一旦代碼被編譯完成,在Sun平臺上所使用的ACC_MACHINE_COMPILED的位則被設定。

  我如何知道JIT編譯器在做什麼?


  環境變量JIT_ARGS允許對Sun Solaris JIT編譯器進行簡單控制。trace 和 exclude(list)是兩個有用的值。要從示例InlineMe中排除(exclude)方法並顯示跟蹤記錄(trace),應將JIT_ARGS 做如下設定:

Unix:
export JIT_ARGS="trace exclude(InlineMe.addCount InlineMe.method1)"

$ java InlineMe
Initializing the JIT library ...
DYNAMICALLY COMPILING java/lang/System.getProperty mb=0x63e74
DYNAMICALLY COMPILING java/util/Properties.getProperty mb=0x6de74
DYNAMICALLY COMPILING java/util/Hashtable.get mb=0x714ec
DYNAMICALLY COMPILING java/lang/String.hashCode mb=0x44aec
DYNAMICALLY COMPILING java/lang/String.equals mb=0x447f8
DYNAMICALLY COMPILING java/lang/String.valueOf mb=0x454c4
DYNAMICALLY COMPILING java/lang/String.toString mb=0x451d0
DYNAMICALLY COMPILING java/lang/StringBuffer. mb=0x7d690
>>>> Inlined java/lang/String.length (4)


  請注意內聯方法(如String.length)是免除的。String.length 也是一個特殊的方法,它一般由Java解釋程序編譯爲一個內部快捷字節碼。當使用JIT編譯器時,由Java解釋程序提供的這些優化失效,從而可以使JIT編譯器能夠理解哪個方法正在被調用。


  如何使用JIT來發揮你的優勢


  首先要記住的一點是,JIT編譯器在第二次調用一個方法時,會獲得大部分速度上的改善。JIT編譯器的確是編譯了整個方法,而不是對其進行逐行解釋,逐行解釋也是一種在運行一個可執行JIT的應用程序時用以改善性能的途徑。這意味着如果代碼僅被調用一次,你將不會看到太大的性能改善。JIT編譯器也將忽略構造函數(class constructor),所以,如果可能的話,應最少量地保留構造函數代碼。


  如果不能預先檢查某些Java邊界條件,JIT編譯器也不能獲得最大的性能改善,這些邊界條件包括零指針(Null pointer)或邊界外數組等異常。JIT編譯器能夠知道出現零指針異常的唯一途徑是通過由操作系統所提供的信號。由於該信號來自操作系統,而不是來自Java虛擬機,因而你的程序會出現性能上的干擾。爲了保證在用JIT運行一個應用程序時,能夠獲取最好的性能,應確保你的代碼完全沒有象零指針或邊界外數組那樣的異常。


  如果你要以遠程調試狀態運行Java虛擬機,或者你要看到源代碼行數而不是看到在你的Java棧跟蹤中的標籤(Compiled Code)的話,你可能需要使JIT編譯器失效。要使JIT編譯器失效,可在你調用解釋器命令時爲JIT編譯器提供一個空白或無效名稱。下面的例子演示了用javac命令將源代碼編譯爲字節碼、以及用兩種形式的java命令在沒有JIT編譯器的情況下調用解釋程序的過程。
javac MyClass.java
java -Djava.compiler=NONE MyClass
or
javac MyClass.java
java -Djava.compiler="" MyClass

第三方工具


  其它一些可用的工具包括可用來減小一般Java類文件尺寸的工具。Java類文件包括一個被稱作常數池(constant pool)的區域。常數池在某一個地方爲類文件保持有一個字符串和其它信息的列表,以備引用。在常數池中可以獲取的諸多信息之一是方法和字段的名稱。


  類文件引用在類中的一個字段作爲對常數池中的一個條目的引用。這意味着只要引用保持相同,則無所謂在常數池中存儲什麼樣的值。 一些工具利用這點將常數池中的字段名和方法名重寫爲縮短的名稱。利用這一技術可以大大減小類文件的尺寸,從而使在網上下載類文件變得簡單。
發佈了117 篇原創文章 · 獲贊 1 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章