2017-05-05 30 views
0

當我初始化StringBuffer的構造與Integer.MAX_VALUE的它拋出OutOfMemoryError,當我加16到它,它拋出NegativeArraySizeException的OutOfMemoryError VS NegativeArraySizeException

public class Test { 
     public static void main(String[] arg) { 
      StringBuffer sb = new StringBuffer(Integer.MAX_VALUE + 16); 
      sb.append("A"); 
     } 
    } 

有一個人幫助我理解這種行爲?

+0

詮釋溢出... – user2717954

+0

閱讀了有關整數溢出 – QBrute

+1

1:*** Integer.MAX_VALUE的+ 16 ***的是,產生負數→無效參數 –

回答

1

你居然問兩個完全不同的問題在這裏,所以他們必須單獨處理。

1.爲什麼new StringBuffer(Integer.MAX_VALUE)會拋出一個OutOfMemoryError

構造函數StringBuffer試圖實例化一個數組char,其大小是您傳遞的值。所以你隱式地嘗試實例化一個大小爲Integer.MAX_VALUE的數組。有兩個原因可能導致實例化數組。

第一個原因是,你真的沒有足夠的堆空間。不知道你的程序中還有什麼事情發生,或者你的堆設置是什麼,我不可能知道這是否會發生在你身上。但是,啓動它時,您可以爲您的JVM選擇最大堆大小,使用-Xmx選項。顯然,假設你的計算機有足夠的內存,你需要將它設置爲幾千兆字節才能使其正常工作(例如-Xmx8g)。

在實例化數組時,OutOfMemoryError的第二個原因是您已經超出了最大數組大小。這絕對是在這裏發生的。最大數組大小不是由Java語言規範定義的,並且它從JVM到JVM都不相同。在大多數現代JVM中,最大陣列大小爲Integer.MAX_VALUE - 2,但有JVM最大爲Integer.MAX_VALUE - 5Integer.MAX_VALUE - 8。無論如何,Integer.MAX_VALUE確實已超出限制。

2.爲什麼new StringBuffer(Integer.MAX_VALUE + 16)會拋出NegativeArraySizeException

這是關於Java中的整數運算。任何int值必須介於Integer.MIN_VALUEInteger.MAX_VALUE之間。此外,當您添加兩個int值時,答案由Java語言規範保證爲​​3210 Integer.MAX_VALUE + 16`,您不會得到數學上正確的答案。實際上,Java所做的就是運行mod 2 。查看它的另一種方法是JVM將添加或減去2的倍數以使答案在正確的範圍內。

這意味着Integer.MAX_VALUE + 16的值實際上在數值上等於,這是一個很大的負數。正如我前面提到的,StringBuffer構造函數試圖實例化一個數組,其大小是您傳遞的值。這種嘗試實例化負數大小的數組會給您帶來NegativeArraySizeException

0

如果您將1添加到Integer.MAX_VALUE您將以Integer.MIN_VALUE結束。從這裏開始,你應該知道,當你添加會發生什麼16

Integer.MAX_VALUE + 16 == Integer.MAX_VALUE + 1 + 15 == Integer.MIN_VALUE + 15 

說明

以整數形式的Java由32位表示,而最顯著一個(最左邊的位)表示整數(0 ==正數,1 ==負數)的符號。

Integer.MAX_VALUE被表示爲:01111111111111111111111111111111。添加1將翻轉所有1 s到0 s並翻轉最左的01導致10000000000000000000000000000000這是一個負數,更具體的Integer.MIN_VALUE

0

StringBuffer使用字符陣列中的其實施爲存儲字符串。下面是它的超類,AbstractStringBuilder,數組實際上得到分配的構造函數:

AbstractStringBuilder(int capacity) { 
    value = new char[capacity]; 
} 

正如你可以看到,新的char[]數組會隨着你在通過能力整數初始化字符數組的大小上限在Java是堆大小或Integer.MAX_VALUE。如果下面的代碼拋出一個錯誤,那麼我的猜測是,你的堆內存耗盡:

StringBuffer sb = new StringBuffer(Integer.MAX_VALUE); 

我本來期望這項工作,假設堆有足夠的空間。但是,試圖分配大小Integer.MAX_VALUE + 16StringBuffer不能的工作,因爲它會超過潛在char[]陣列的最大尺寸。

+0

你是對的... :)一如既往 –

+0

我可能被忽略了信息關於整數溢出,這也可能在數組分配發生之前發生。但這是發生什麼事情的一個可能的解釋。 –

+0

OOM是有道理的,但這裏的問題是負整數異常? –