2011-03-03 60 views
69

我注意到了一些意想不到的行爲(與我個人的預期相關),並且我想知道如果JVM中存在某個錯誤,或者這是一個附帶案例,我不理解其中的一些細節究竟應該發生什麼。假設我們本身有一個主要方法如下代碼:這是JVM錯誤還是「預期行爲」?

int i; 
int count = 0; 
for(i=0; i < Integer.MAX_VALUE; i+=2){ 
    count++; 
} 
System.out.println(i++); 

一個天真的預期是,這將打印Integer.MAX_VALUE-1,最大的甚至可表示int。但是,我相信整數算術應該在Java中「翻轉」,所以在Integer.MAX_VALUE中加1應該會導致Integer.MIN_VALUE。由於Integer.MIN_VALUE仍然小於Integer.MAX_VALUE,因此循環將不斷迭代負整數。最終它會回到0,這個過程應該重複爲一個無限循環。

當我實際運行此代碼時,我得到了非確定性結果。打印出來的結果往往是五十萬左右,但確切的數值會有所不同。因此,不僅當循環終止時,我認爲它應該是一個無限循環,但它似乎隨機終止。這是怎麼回事?

我的猜測是,這可能是JVM中的一個錯誤,或者有很多時髦的優化會導致這種預期的行爲。這是什麼?

+0

這是所有在你的主要方法? – 2011-03-03 16:23:42

+0

是的......這很重要嗎? – 2011-03-03 16:24:26

+0

@Michael:只要檢查一下是否有一些時髦的線程正在進行。在我的機器上總是打印出2147483640,但這仍然是意想不到的。 – 2011-03-03 16:26:13

回答

4

嘗試增加System.out.println(count);

我不知道是否有發生,因爲計數從不讀取優化。

編輯 - 另一個答案給出了Oracle錯誤跟蹤器中錯誤的鏈接。由此得出:

  • 6196102特別提到存在一個規範化錯誤,其中Integer.MAX_VALUE有關。
  • Java必須嘗試優化循環,因爲count從不讀取。

然而,這是不太可能在實踐中發生的,這是因爲:

  • Integer.MAX_VALUE是一個不太可能的環路保護
  • 通常循環做的工作,不會允許在首位這種優化
+0

這使得我的測試運行至少一致。所以這是一個優化問題? – 2011-03-03 16:30:19

15

這是奇怪的。它當然看起來像一個錯誤。每次使用相同的代碼我都會得到相同的結果,但對代碼的微小更改會改變結果。例如:

public class Test { 
    public static void main(String[] args) { 
    int i; 
    int count = 0; 
    for (i = 0; i < Integer.MAX_VALUE; i+=2) { 
     count++; 
    } 
    System.out.println(i); 
    System.out.println(i < Integer.MAX_VALUE); 
    } 
} 

...始終打印2147483640,真實

,而這一點:

public class Test { 
    public static void main(String[] args) { 
    int i; 
    for (i = 0; i < Integer.MAX_VALUE; i+=2) { 
    } 
    System.out.println(i); 
    System.out.println(i < Integer.MAX_VALUE); 
    } 
} 

始終打印-2147483648和真實。

非常非常奇怪。

(這是在Linux上運行的OpenJDK 1.6虛擬機。)

編輯:在Windows 7上運行的OpenJDK 1.7,我看不出問題:

java version "1.7.0-ea" 
Java(TM) SE Runtime Environment (build 1.7.0-ea-b78) 
Java HotSpot(TM) Client VM (build 17.0-b05, mixed mode, sharing) 
2

這似乎是一個循環的優化,我觀察到相同的結果,但如果我也打印出來count然後結果改變。

I.e.

int i; 
    int count = 0; 
    for(i=0; i < Integer.MAX_VALUE; i+=2){ 
     count++; 
    } 
    System.out.println(count); 
    System.out.println(i++); 

可生產2147483638而原始代碼產生457158(或類似)

0
java version "1.6.0_22" 
Java(TM) SE Runtime Environment (build 1.6.0_22-b04) 
Java HotSpot(TM) Client VM (build 17.1-b03, mixed mode, sharing) 

按預期工作。無限循環

+1

呵呵?無窮?? – totten 2014-12-24 14:17:15

相關問題