java代碼的動態編譯問題

    上回聽了一堂關於Java動態編譯和靜態編譯的課,覺得自己對這方面瞭解不多,於是整理下知識點,也上網查了些資料,對Java的動態編譯有了一些基礎的瞭解。
    Java動態編譯器,通常稱作即時(Just-in-time,JIT)編譯器。程序運行時,JIT 編譯器選擇將最頻繁執行的方法編譯成本地代碼。運行時再進行本地代碼編譯而不是在程序運行前進行編譯,保證了可移植性的需求。但動態編譯可能嚴重干擾程序操作,因爲編譯器必須與應用程序共享 CPU。對於Java代碼,靜態編譯可以極大地提高 Java 性能,但同時也帶來了很多複雜性。
    Java 程序最初是通過 Java SDK 的 javac程序編譯成本地的與平臺無關的class文件,可將此格式看作 Java 平臺,因爲它定義了執行 Java 程序所需的所有信息。Java 程序執行引擎,也稱作 Java 運行時環境(JRE),包含了爲特定的本地平臺實現 Java 平臺的虛擬機。
    儘管通過 JIT 編譯保持了平臺無關性,但是付出了一定代價。因爲在程序執行時進行編譯,所以編譯代碼的時間將計入程序的執行時間。爲了克服這個缺點,現代的 JIT 編譯器使用了下面兩種方法的任意一種(某些情況下同時使用了這兩種方法)。第一種方法是:編譯所有的代碼,但是不執行任何耗時多的分析和轉換,因此可以快速生成代碼。第二種方法是:將編譯資源只分配給少量的頻繁執行的方法(通常稱作熱方法),這種方法有效地實現了編譯性能成本的最小化。

動態編譯優點:
    動態編譯能夠比靜態編譯語言更好地生成代碼,現代的 JIT 編譯器常常向生成的代碼中插入掛鉤以收集有關程序行爲的信息,以便如果要選擇方法進行重編譯,就可以更好地優化動態行爲。比如說收集一個特定 arraycopy操作的長度。如果發現每次執行操作時該長度基本不變,則可以爲最頻繁使用的 arraycopy長度生成專門的代碼,或者可以調用調整爲該長度的代碼序列。由於內存系統和指令集設計的特性,用於複製內存的最佳通用例程的執行速度通常比用於複製特定長度的代碼慢。因爲動態編譯器通常只是集中編譯少量的熱方法,所以可以執行更主動的分析來生成更好的代碼,使編譯的回報更高。事實上,大部分現代的 JIT 編譯器也支持重編譯被認爲是熱方法的方法。
動態編譯缺點:
    大量的初始編譯可能直接影響應用程序的啓動時間。不僅這些編譯延遲了應用程序達到穩定狀態的時間,而且在準備階段中頻繁執行的方法可能對應用程序的穩定狀態的性能所起的作用也不大。如果 JIT 編譯會延遲啓動又不能顯著改善應用程序的長期性能,則執行這種編譯就非常浪費。
    其次,有些應用程序完全不能忍受動態編譯帶來的延遲。如 GUI 接口之類交互式應用程序就是這樣的例子。在這種情況下,編譯活動可能對用戶使用造成不利影響,同時又不能顯著地改善應用程序的性能。
    最後,用於實時環境並具有嚴格的任務時限的應用程序可能無法忍受編譯的不確定性性能影響或動態編譯器本身的內存開銷。
    因此,雖然 JIT 編譯技術已經能夠提供與靜態語言性能相當的性能水平,但是動態編譯並不適合於某些應用程序。
發佈了33 篇原創文章 · 獲贊 11 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章