通过虚拟内存与 RAM 可行的内存大小

Memory size feasible via Virtual Memory vs RAM

我正在尝试实例化一个巨大的 ArrayList

List<Integer> list = new ArrayList<Integer>(Integer.MAX_VALUE);  

运行 在日食中我得到:

java.lang.OutOfMemoryError: Requested array size exceeds VM limit  

如果我这样做:

List<Integer> list = new ArrayList<Integer>(Integer.MAX_VALUE - 2);  

我得到一个不同的错误:

Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory failed; error='The paging file is too small for this operation to complete'   

#
# there is insifficent memory for the Java Runtime Environment to continue.   

我在 eclipse 的 运行 配置中使用以下设置启动程序:
-Xmx8G

那么这里的问题是什么?即使我增加到 -Xmx16G 它仍然会给出相同的错误

更新
我有点困惑,RAM 的实际大小在这里重要吗?由于分页,进程是否可以访问无限的虚拟内存?

I am bit confused, does the actual size of RAM matter here?

是的,确实如此。

Don't processes have access to unlimited virtual memory thanks to paging?

是的,他们这样做......模数你需要磁盘 space 来保存虚拟内存页面。事实上, 就是您收到此错误的原因:

The paging file is too small for this operation to complete.

此“修复”将使分页文件更大。这必须在 OS 级别完成。

但是,分页意味着操作系统必须在需要时将页面从磁盘复制到内存。为了给它们腾出空间,它必须将其他(脏)页面从 RAM 复制到磁盘。所有这些复制使用 CPU 和磁盘 I/O 带宽并减慢您的程序。

典型的 (C / C++) 程序通常可以在一定程度上解决这个问题,具体取决于应用程序的内存访问模式。但是在 Java 中,您会遇到偶尔运行 GC 的问题。在一段时间内,GC 将以(本质上)随机顺序访问大量页面中的对象。 “完整”垃圾收集更糟糕。

如果应用程序访问的设置页面(即“工作集”)的大小大于可用 RAM 页面的数量,您可能会“抖动”;即用页面的读写使 I/O 系统饱和。这对性能来说真的很糟糕。在极端情况下,它会使 OS 无响应。

因此,运行Java 堆大于可用物理 RAM 的应用程序是一件有潜在危险的事情。