当我使用Integer.MAX_VALUE初始化StringBuffer构造函数时,它会抛出OutOfMemoryError
,当我向其中添加16时,它会抛出NegativeArraySizeException
public class Test {
public static void main(String[] arg) {
StringBuffer sb = new StringBuffer(Integer.MAX_VALUE + 16);
sb.append("A");
}
}
有人可以帮助我理解这种行为吗?
最佳答案
您实际上在这里提出了两个完全不同的问题,因此必须分别解决它们。
<强>1。为什么 new StringBuffer(Integer.MAX_VALUE)
会抛出 OutOfMemoryError
?
StringBuffer
构造函数尝试实例化一个 char
数组,其大小是您传递的值。因此,您隐式地尝试实例化一个大小为 Integer.MAX_VALUE
的数组。实例化数组时可能出现 OutOfMemoryError
的原因有两个。
第一个原因是您确实没有足够的堆空间。如果不知道您的程序中还发生了什么,或者您的堆设置是什么,我就不可能判断您是否会发生这种情况。但是您可以在启动时使用 -Xmx
选项选择 JVM 的最大堆大小。显然,假设您的计算机有足够的 RAM,您需要将其设置为几 GB 才能使其正常工作(例如 -Xmx8g
)。
实例化数组时出现 OutOfMemoryError
的第二个原因是超出了最大数组大小。这肯定发生在这里。 Java 语言规范没有定义最大数组大小,并且它随 JVM 的不同而变化。在大多数现代 JVM 中,最大数组大小为 Integer.MAX_VALUE - 2
,但也有 JVM,其中最大值为 Integer.MAX_VALUE - 5
或 Integer。 MAX_VALUE - 8
。无论如何,Integer.MAX_VALUE
肯定超出了限制。
<强>2。为什么 new StringBuffer(Integer.MAX_VALUE + 16)
会抛出 NegativeArraySizeException
?
这与 Java 中的整数运算有关。任何 int
值都必须介于 Integer.MIN_VALUE
和 Integer.MAX_VALUE
之间。此外,当您添加两个 int
值时,Java 语言规范保证答案是一个 int。因此,当您计算
Integer.MAX_VALUE + 16`时,您不会得到数学上正确的答案。事实上,Java 所做的就是工作 mod 232。另一种看待它的方式是,JVM 将添加或减去 232 的倍数,以使答案处于正确的范围内。
这意味着 Integer.MAX_VALUE + 16
的值实际上等于 Integer.MAX_VALUE + 16 -
232,这是一个很大的负数。正如我之前提到的,StringBuffer
构造函数尝试实例化一个数组,该数组的大小就是您传递的值。尝试实例化负大小的数组会导致 NegativeArraySizeException
。
关于java - OutOfMemoryError 与 NegativeArraySizeException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43797189/