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

标签 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);
  }
}

据我所知,用于 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/

相关文章:

java - 将 Jersey 本地 REST 服务引入 openshift

java - 无法处理大于 65535 个字符的字符串文字。编译器抛出 IllegalArgumentException

Java 优化 : speed of inner loops inconsistent?

java - 大字符串导致的 OutOfMemoryException

java - 我无法使用 BlueJ 打印简单的 JAVA 代码,在 CMD 中工作

java - 使用Maven,如何正确部署依赖于J2EE/JPA JAR的WAR?

java - 不同 JFrame 之间的信息交换

jvm - iReport 5.5.0 无法启动

android - 如何在 Android 中的 GridView 内的 imageView 上设置布局参数

java - 构建 Apache FOP 时系统资源不足