java - OutOfMemoryError 与 NegativeArraySizeException

标签 java stringbuffer

当我使用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 - 5Integer。 MAX_VALUE - 8。无论如何,Integer.MAX_VALUE 肯定超出了限制。

<强>2。为什么 new StringBuffer(Integer.MAX_VALUE + 16) 会抛出 NegativeArraySizeException

这与 Java 中的整数运算有关。任何 int 值都必须介于 Integer.MIN_VALUEInteger.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/

相关文章:

java - "StringBuilders are not thread-safe"是什么意思?

java - 将多行 JTextArea 写入 txt 文件

java - 静态变量和方法

java - Maven编译报错try-with-resources

java - Java Web Start 的替代品?

java - 如果您的数据库层只有 JDBC,是否值得使用 Spring?

java - 在线读取 XML 并存储它(使用 Java)

java - java 是否可以在二分查找中检查特殊字符?

java - 为什么在 1.5 之前的 java 版本中用 StringBuilder 替换 StringBuffer 对象是不安全的

Java StringBuilder(StringBuffer) 的 ensureCapacity() : Why is it doubled and incremented by 2?