java OOM关于创建2个十亿整数的数组

Nit*_*raj 5 java jvm out-of-memory jvm-arguments

我正在用Java编写简单的程序来创建2个10亿大小的int数组。我用-Xms10G运行了该程序,即10GB的内存仍然出现OOM错误。以下是代码段。

public class TestBigIntArraySize {
  public static int arraySize = 1000_000_000;
  public static int [] firstArray = new int[arraySize];
  public static int [] secondArray = new int[arraySize];

  public static void main(String[] args) {
    System.out.println(1000_000_000 * Integer.SIZE);
  }
}
Run Code Online (Sandbox Code Playgroud)

就我所能想到的,用于十亿个int数组的内存将是System.out.println(1000_000_000 * Integer.SIZE); 返回1,935,228,928,小于2GB。因此,我的程序总要求最大为4GB。

即使我在方法调用中创建数组并返回数组或静态数组(如下所示)或在main()中,也会收到错误消息。工作所需的内存是12G,是我预期的3倍。我正在使用oracle java:jdk1.8.0_201

我尝试了-Xms10G -XX:NewRatio = 1 ---可行的选项。

但是我想进一步减少内存占用。

我尝试通过给eden提供更多内存的选项,-Xms9G -XX:NewRatio=0.5但是java抱怨非法参数。

我尝试通过选项将数组直接分配给旧gen的选项-Xms9G -XX:NewRatio=1 -XX:PretenureSizeThreshold=10000。但这也给OOM。

这只是一个实验项目,我只是在操纵阵列的位置。我想用最小的内存做到这一点。有人可以建议如何去做吗?什么Java选项,为什么?

gle*_*e8e 3

因此,假设乘以位长度可能不是获取字节数的最佳方法。正如 @mayamar 所提到的,您的实际内存使用量约为 2*4 giga byte

无论如何,让我们开始实际的调音乐句。4GB 可能太大了,将直接存储在旧代中。所以你需要增加老一代的大小。更改新的一代设置可能会起作用,但那是......好吧,那么您实际上就关闭了旧的一代。它可能会对测试用例的其他部分造成损害。

您尝试NewRatio=1将新旧世代的比例设置为 1:1,而不是更好的比例,例如 1:100。然而,如果您将比率设置得太大,JVM 可能无法启动(VM 初始化期间进行 GC)。最好只用 指定它MaxNewSize

最后,运行与此类似的东西将非常接近您的“最小化内存占用”要求。

java -Xmx8400000000 -XX:MaxNewSize=30M -XX:OldSize=8300000000 TestBigIntArraySize 
Run Code Online (Sandbox Code Playgroud)

注意:最好留出几十兆字节,因为 JVM 本身需要内存来运行。如果您的程序不像 MVCE 那么小,并且不希望 GC 时不时地启动,则需要留出更多空间。