我正在用 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); 返回小于 2GB 的 1,935,228,928。所以我的程序总需求最大为 4GB。
即使我在方法调用中创建数组并返回数组或静态(如下所示)或在 main() 内部,我也会出错。 它工作所需的内存是 12G,是我预期的 3 倍。 我正在使用 oracle 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 千兆字节。
无论如何,让我们开始真正的调音乐句。 4GB 可能太大,将直接存储在老一代中。所以你需要增加老一代的规模。更改新一代设置可能会起作用,但那是......好吧,你实际上是在关闭旧一代。它可能会对您的测试用例的其他部分造成伤害。
你的尝试 NewRatio=1
使新老一代的比例为 1:1,而不是更好的比例,例如1:100。但是,如果您将比率设置得太大,JVM 可能无法启动(VM 初始化期间的 GC)。最好只用 MaxNewSize
指定它。
最后,运行与此类似的程序将非常接近您的“最小化内存占用”要求。
java -Xmx8400000000 -XX:MaxNewSize=30M -XX:OldSize=8300000000 TestBigIntArraySize
注意:JVM本身运行需要内存,最好留几十兆。如果您的程序不像您的 MVCE 一样小,并且您不希望 GC 时不时地启动,则需要留出更多空间。
关于java OOM 关于创建 2 个 10 亿个整数的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55323648/