2017-05-05 56 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是有道理的,但这里的问题是负整数异常? –