Java OutOfMemoryError vs NegativeArraySizeException

Java OutOfMemoryError vs NegativeArraySizeException,java,stringbuffer,Java,Stringbuffer,当我用Integer.MAX_值初始化StringBuffer构造函数时,它抛出OutOfMemoryError,当我向其中添加16时,它抛出NegativeArraySizeException 有人能帮我理解这个行为吗?如果你给Integer.MAX\u值加上1,你将得到Integer.MIN\u值。从这里开始,您应该知道添加16时会发生什么: 解释 Java中的整数由32位表示,而最左边最重要的一位表示整数0==正,1==负的符号 Integer.MAX_值表示为:0111111111111

当我用Integer.MAX_值初始化StringBuffer构造函数时,它抛出OutOfMemoryError,当我向其中添加16时,它抛出NegativeArraySizeException

有人能帮我理解这个行为吗?

如果你给Integer.MAX\u值加上1,你将得到Integer.MIN\u值。从这里开始,您应该知道添加16时会发生什么:

解释

Java中的整数由32位表示,而最左边最重要的一位表示整数0==正,1==负的符号

Integer.MAX_值表示为:011111111111111111。添加1会将所有1翻转为0,并将最左边的0翻转为1,从而产生100000000000000000000000,这是一个负数,更具体的整数.MIN\u值。

StringBuffer在其实现中使用字符数组来存储字符串。下面是它的超类AbstractStringBuilder的构造函数,数组实际上是在这里分配的:

AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}
如您所见,一个新的char[]数组使用您传入的容量整数进行初始化。Java中字符数组的最大大小是heap size或Integer.max_值中的较小值。如果以下代码抛出错误,那么我猜您的堆内存不足:

StringBuffer sb = new StringBuffer(Integer.MAX_VALUE);

假设堆有足够的空间,我会认为这是可行的。但是尝试分配一个大小为Integer.MAX_VALUE+16的StringBuffer无法工作,因为它将超过基础char[]数组的最大大小。

您实际上在这里提出了两个完全不同的问题,因此必须分别解决它们

一,。为什么新的StringBufferInteger.MAX_值抛出OutOfMemoryError

StringBuffer构造函数尝试实例化char数组,其大小是您传递的值。因此,您隐式地尝试实例化一个大小为Integer.MAX_值的数组。实例化数组时可能会出现OutOfMemoryError的原因有两个

第一个原因是您确实没有足够的堆空间。如果不知道程序中还发生了什么,或者堆设置是什么,我就不可能知道这是否会发生在您身上。但是,您可以在启动JVM时使用-Xmx选项为其选择最大堆大小。显然,如果您的计算机有足够的RAM,您需要将其设置为几GB才能使其正常工作,例如Xmx8g

在实例化数组时出现OutOfMemoryError的第二个原因是您已超过了最大数组大小。这肯定发生在这里。Java语言规范没有定义最大数组大小,它因JVM而异。在大多数现代JVM中,最大数组大小为Integer.MAX_值-2,但也有JVM的最大数组大小为Integer.MAX_值-5或Integer.MAX_值-8。在任何情况下,Integer.MAX_值都肯定超过限制

二,。为什么新的StringBufferInteger.MAX_值+16抛出NegativeArraySizeException

这与Java中的整数算术有关。任何int值必须介于Integer.MIN_值和Integer.MAX_值之间。另外,当您添加两个int值时,Java语言规范保证答案为int。因此,当您计算integer.MAX_VALUE+16`时,您将无法得到数学上正确的答案。事实上,Java所做的就是使用mod 232。另一种看待它的方式是JVM将增加或减少232的倍数,以使答案在正确的范围内


这意味着Integer.MAX_value+16的值实际上在数字上等于Integer.MAX_value+16-232,这是一个很大的负数。正如我前面提到的,StringBuffer构造函数尝试实例化一个数组,该数组的大小是您传递的值。尝试实例化一个负大小的数组会给您带来NegativeArraySizeException。

Int overflow…了解整数溢出1st:integer.MAX_VALUE+16是一个产生负数的溢出→ 无效参数整型加整型始终是整型,即使加法超出了整型的限制。我重新打开了这个问题,因为整型溢出可能不是这里发生的唯一事情。我可能遗漏了关于整型溢出的信息,甚至在数组分配发生之前也可能发生整型溢出。但这是一种可能的解释。OOM是合理的,但这里的问题是负整数例外??
AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}
StringBuffer sb = new StringBuffer(Integer.MAX_VALUE);