java 创建 2 个 10 亿整数数组时出现 OOM
java OOM on creating 2 arrays of one billion ints
我正在 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);
}
}
据我所知,用于 10 亿个 int 数组的内存将是 System.out.println(1000_000_000 * Integer.SIZE);
其中 returns 1,935,228,928 小于 2GB。所以我的程序总需求最大为 4GB。
即使我在方法调用和 return 数组或静态(如下所示)或在 main() 中创建数组,我也会出错。
它工作所需的内存是 12G,是我预期的 3 倍。
我正在使用甲骨文 java : jdk1.8.0_201
我尝试了选项 -Xms10G -XX:NewRatio=1 --- 有效。
但我想进一步减少内存占用。
我尝试通过 -Xms9G -XX:NewRatio=0.5
选择为 eden 提供更多内存,但 java 抱怨非法参数。
我尝试了 -Xms9G -XX:NewRatio=1 -XX:PretenureSizeThreshold=10000
直接将数组分配给老一代的选项。但这也给OOM。
这只是一个实验项目,我只是在适当地操纵数组。我想在 尽可能小的内存 中完成。
有人可以建议如何去做吗?什么 java 选项以及为什么?
所以假设乘 位长度 可能不是获得字节数的最佳方法。正如@mayamar 所提到的,您的实际内存使用量约为 2*4 gigabyte.
无论如何,让我们开始真正的调音乐句吧。 4GB 可能太大,将直接存储在老一代中。所以你需要增加老一代的规模。更改新一代设置可能会起作用,但那是......好吧,你实际上是在关闭旧一代。它可能会对您的其他部分测试用例造成伤害。
您的尝试 NewRatio=1
使新老一代的比例 1:1,而不是更好的东西,例如1:100。但是,如果您将比率设置得太大,JVM 可能无法启动(VM 初始化期间的 GC)。最好只指定 MaxNewSize
.
最终,运行 与此类似的内容将非常接近您的 "minimize memory footprint" 要求。
java -Xmx8400000000 -XX:MaxNewSize=30M -XX:OldSize=8300000000 TestBigIntArraySize
注意:JVM本身运行需要内存,最好留几十兆。如果你的程序不像你的 MVCE 那么小,如果你不希望 GC 时不时地启动,你将需要遗漏更多 space。
与here相同的问题。
在默认使用Parallel GC的JDK8中,10GB的heap分为6.67GB Old Generation + 3.33GB Young Generation。因此,没有空间容纳两个连续的 3.72 GB 块(10 亿个四字节整数)。
解决该问题的最简单方法是打开 G1 GC 并完全避免棘手的生成大小调整。然后,您的示例将使用 8 GB 堆:
java -XX:+UseG1GC -Xmx8g TestBigIntArraySize
我正在 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);
}
}
据我所知,用于 10 亿个 int 数组的内存将是 System.out.println(1000_000_000 * Integer.SIZE); 其中 returns 1,935,228,928 小于 2GB。所以我的程序总需求最大为 4GB。
即使我在方法调用和 return 数组或静态(如下所示)或在 main() 中创建数组,我也会出错。 它工作所需的内存是 12G,是我预期的 3 倍。 我正在使用甲骨文 java : jdk1.8.0_201
我尝试了选项 -Xms10G -XX:NewRatio=1 --- 有效。
但我想进一步减少内存占用。
我尝试通过 -Xms9G -XX:NewRatio=0.5
选择为 eden 提供更多内存,但 java 抱怨非法参数。
我尝试了 -Xms9G -XX:NewRatio=1 -XX:PretenureSizeThreshold=10000
直接将数组分配给老一代的选项。但这也给OOM。
这只是一个实验项目,我只是在适当地操纵数组。我想在 尽可能小的内存 中完成。 有人可以建议如何去做吗?什么 java 选项以及为什么?
所以假设乘 位长度 可能不是获得字节数的最佳方法。正如@mayamar 所提到的,您的实际内存使用量约为 2*4 gigabyte.
无论如何,让我们开始真正的调音乐句吧。 4GB 可能太大,将直接存储在老一代中。所以你需要增加老一代的规模。更改新一代设置可能会起作用,但那是......好吧,你实际上是在关闭旧一代。它可能会对您的其他部分测试用例造成伤害。
您的尝试 NewRatio=1
使新老一代的比例 1:1,而不是更好的东西,例如1:100。但是,如果您将比率设置得太大,JVM 可能无法启动(VM 初始化期间的 GC)。最好只指定 MaxNewSize
.
最终,运行 与此类似的内容将非常接近您的 "minimize memory footprint" 要求。
java -Xmx8400000000 -XX:MaxNewSize=30M -XX:OldSize=8300000000 TestBigIntArraySize
注意:JVM本身运行需要内存,最好留几十兆。如果你的程序不像你的 MVCE 那么小,如果你不希望 GC 时不时地启动,你将需要遗漏更多 space。
与here相同的问题。
在默认使用Parallel GC的JDK8中,10GB的heap分为6.67GB Old Generation + 3.33GB Young Generation。因此,没有空间容纳两个连续的 3.72 GB 块(10 亿个四字节整数)。
解决该问题的最简单方法是打开 G1 GC 并完全避免棘手的生成大小调整。然后,您的示例将使用 8 GB 堆:
java -XX:+UseG1GC -Xmx8g TestBigIntArraySize