2012-07-25 30 views
3

可能重複:
Why doesn't the JVM cache JIT compiled code?即時編譯 - 儲存VS總是在做

據我所知,JIT編譯使用熱點的機制編譯爲本地代碼,這是非常非常快因爲它對操作系統,Hardwards等進行了優化。

我的問題是,爲什麼Java不會將JIT編譯代碼存儲在文件中的某處並使用相同的未來目的?這也可以減少'最初的熱身'時間。

請讓我知道我在這裏失蹤。

添加到我的問題: 爲什麼Java不會將完整的代碼編譯爲本機並始終使用它(對於特定的JVM,OS,平臺)?爲什麼是JIT?

+0

添加相關問題! – 2012-07-25 15:08:43

回答

2

如果我沒有記錯,JIT編譯的代碼的緩存和共享已經嘗試過,並且發現不是一個好主意。

一方面,一個現代HotSpot JIT編譯器在當前CPU模型的上下文中生成和優化代碼,以及當前執行的使用模式。如果它要緩存已編譯的代碼,那麼代碼很可能不是最優的。

另一方面,顯然有各種欺騙技術問題。例如,高速緩存的代碼成爲潛在的安全漏洞。例如,代碼區域需要被所有共享它的應用程序/用戶寫入。但這意味着一個用戶可能會干擾其他用戶應用程序的運行。

+0

爲什麼緩存的優化代碼必須在用戶之間共享?通常在用戶主目錄中有一個.java目錄來存儲這些數據。 – Puce 2012-07-25 16:12:15

+0

從前面的運行中收集的數據優化的代碼很可能比未優化的代碼更好,我猜。 – Puce 2012-07-25 16:13:54

+0

@Puce - 如果存在優化程度不佳的代碼會阻止JVM收集使用統計信息,或者JIT編譯器嘗試優化。這是一個複雜的問題領域,其中「直觀明顯的」事物不一定是正確的。 – 2012-07-26 01:54:58

2

我自己也問過這個問題。我得到的印象是很難得到正確的,並避免擁有包含過時代碼的商店。

解決此問題的一種方法是執行-XX:+PrintCompilation,並編寫一個簡短的預熱程序以加熱這些方法。

3

雖然有保證您總是使用JVM,但不保證您始終使用相同的JVM。熱點優化代碼僅適用於您的機器。

使用Java,不能保證代碼對於JVM是本地的。小程序是一個很好的例子,Webstart也說明了這一點。通用的「保持優化」只會在很少運行代碼時造成緩存混亂,並會在保留優化擴展的地方產生問題。

它也會在知道保持磁盤緩存多長時間時產生一個難題,並且您不必重新編譯'class'文件來驗證緩存是否正確地「釋放」了類文件?除了可選的串行版本uid之外,Java沒有相同類文件標識符的「此版本」。

也許有一個變通方法通過檢查總結中的類文件,並把它編譯類的領域,但我討厭考慮啓動了掃描所有緩存的機器特定的代碼負責一個JVM的時間,建立一個表干預類加載器,然後使用優化代碼檢查加載類的校驗和。

2

它存在於.Net(它在很多方面類似於java),它被稱爲NGEN。所以我不明白爲什麼它不能存在於Java中。

我可以看到兩個原因,它沒有這樣做:

  • Java沒有一個好的ID機制像.NET有其組裝。但散列確實可以使用(在jar或class級別)。
  • 它將主要(只有?)在應用程序啓動時受益。自從JRE6以來,啓動速度變得更快了。
2

某些JVM(如IBM的)確實有「ahead of time shared JIT code」。這很難做(因爲其他答案指出),因爲一個JVM一次使用的類文件可能與下次使用的類文件不同,即使它們具有相同的名稱。因此,需要很多邏輯來證明「我之前看到的A類與我現在擁有的A類真的是一樣的」。另一個問題是JITed代碼通常包含特定於地址空間的值(例如:給定靜態變量的地址或另一個JITed方法的入口點),而且每個JIT代碼都可以(當然會更改) JVM調用,所以在處理這些問題時必須小心。

AOT代碼提供的性能是真實的,而且功能非常值得使用,具體情況取決於環境。 (具體來說:事情不會改變運行,等等。 - 例如調用相同版本的應用程序服務器或Eclipse,例如)

+0

「因此,需要很多邏輯來證明」我之前看到的A類與我現在擁有的A類真的是一樣的「。 - >看看日期? – 2013-09-14 03:01:44

+0

所以是的,日期是首先看的東西,但它往往是不夠的。舉一個簡單的例子,2個As(具有相同的大小和時間戳)可能在2個不同的jar文件中,搜索順序在運行之間反轉。您還假設簡單的類加載器具有基於文件的.class表示形式(核心JVM本身在引導後實際上並不真正知道)。 – 2013-10-03 02:00:53