我正在用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);
}
}
据我所知,用于十亿个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 ---可行的选项。
但是我想进一步减少内存占用。
我尝试通过-Xms9G -XX:NewRatio=0.5
给伊甸园提供更多内存的选项,但是java抱怨非法参数。
我尝试了通过-Xms9G -XX:NewRatio=1 -XX:PretenureSizeThreshold=10000
直接将数组分配给旧一代的选项。但这也给了OOM。
这只是一个实验项目,我只是在操纵阵列的位置。我想用尽可能小的内存来做。 有人可以建议如何去做吗?什么是Java选项,为什么?
答案 0 :(得分:3)
因此,假设乘以位长可能不是获取字节数的最佳方法。正如@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偶尔出现,您将需要留出更多空间。
答案 1 :(得分:2)
与here相同的问题。
在默认情况下使用Parallel GC的JDK 8中,将10 GB的堆划分为6.67 GB的旧一代+ 3.33 GB的年轻一代。因此,没有足够的空间容纳两个连续的3.72 GB的块(10亿个四字节整数)。
解决问题的最简单方法是打开G1 GC并完全避免棘手的生成大小调整。然后,您的示例将使用8 GB的堆:
java -XX:+UseG1GC -Xmx8g TestBigIntArraySize