JIT觸發器多次執行某段代碼後。
HotSpot JVM將嘗試識別代碼中的「熱點」。熱點是您執行很多次代碼的部分。爲此,JVM將「計數」各種指令的執行情況,當它確定某個片段頻繁執行時,它將觸發JIT。 (這是一個近似值,但這很容易理解)。 JIT(Just-In-Time)接受這段代碼,並試圖使其更快。
使用的JIT,使你的代碼運行速度更快的技術有很多,但最常見的造成混亂的一個是:
- 它將嘗試以確定是否那塊代碼使用的變量沒有用在其他地方(無用的變量),並刪除它們。
- 如果您獲取和同一鎖多次釋放(如調用同一個對象的synchronized方法),它可以一次性獲得鎖定,如果你訪問對象的成員做一個synchronized塊
- 所有來電那些沒有被聲明爲volatile的,它可以決定優化它(在寄存器和類似的地方放置值),在多線程代碼中創建奇怪的結果。
- 它會內聯方法,以避免通話費用。
- 它會將字節碼轉換爲機器碼。
- 如果循環完全無用,它可能會被完全刪除。
所以,你的問題的正確答案是,被JITed後的空循環,沒有時間執行..最有可能不存在了。
同樣,還有很多其他的優化,但根據我的經驗,這些是最令人頭痛的問題。此外,JIT在任何新版本的Java中都得到了改進,有時它甚至會根據平臺而有所不同(因爲它在某種程度上是平臺特定的)。由JIT完成的優化難以理解,因爲即使在最近的Java版本中,這些優化中的某些優化已直接移至編譯器中,您通常無法使用javap查找它們並檢查字節碼(例如,自從Java 6編譯器能夠檢測和警告未使用的局部變量和私有方法)。
如果您正在編寫一些循環來測試某些內容,通常是將循環放入方法中,在計時之前調用該方法幾次以使其「加速」,然後執行定時循環。
這通常會觸發在你們這樣一個簡單的程序的JIT,即使不能保證它確實會觸發(或者說,它甚至存在於一定的平臺)。
如果你想得到關於JIT或非JIT時間的偏執(我做過):做第一輪,計算每個執行循環的時間,並等待時間穩定(例如,與平均值的差值小於10 %),然後從「真實」時間開始。
我認爲'System.nanoTime()'更是爲這個測試表明(客戶端/服務器的虛擬機也應該做一些差異) –
是啊,沒錯,毫秒往往過於粗粒度。 –