Java 为什么要从内存异常中获取堆?

Java 为什么要从内存异常中获取堆?,java,jvm,heap,Java,Jvm,Heap,我试图分配一个大矩阵(大约10GB)。我在使用64位JVM的64位机器上工作。然后,我的进程应该有2^64字节可用,并且我已经将JVM堆大小设置为128G(如果需要的话,我的机器中有16GB的RAM)。我的理解是,我应该从操作系统获得内存,不需要的矩阵单元将被操作系统交换掉。但是我得到了上面的例外 编辑: 这就是我定义矩阵的方式: Jama.Matrix A = new Matrix(num_words, num_documents); 其中num_words约为100k,num_docume

我试图分配一个大矩阵(大约10GB)。我在使用64位JVM的64位机器上工作。然后,我的进程应该有
2^64
字节可用,并且我已经将JVM堆大小设置为128G(如果需要的话,我的机器中有16GB的RAM)。我的理解是,我应该从操作系统获得内存,不需要的矩阵单元将被操作系统交换掉。但是我得到了上面的例外

编辑:

这就是我定义矩阵的方式:

Jama.Matrix A = new Matrix(num_words, num_documents);
其中
num_words
约为100k,
num_documents
约为35k。 还值得一提的是,该类型是
double

编辑2:

相关旗帜:

-Xms40m
-Xmx128g
-d64
以下是一些描述:

Xms -> the init memory that should be allocated in the start up in MB.
Xmx -> the Max amount of memory that your application can get in MB e.g Xmx2048m.
-XX:MaxNewSize= -> the max S1 and S2 memory size
-XX:NewSize= -> init S1 and S2 size

因此,在您的例子中,如果您希望尽可能多地分配内存,那么您需要说,例如,
16*1024=16384或16g
,并且
-XX:MaxNewSize=和-XX:NewSize=
将其设置为Xmx的40%

在java中可以分配的内存并不取决于RAM,而是取决于运行JVM时指定的命令行选项
-Xmx
。若RAM中的内存不足,JVM将从swap接收它,并且(我相信)甚至不知道这一点

但是,

  • 在某些操作系统(Windows XP)中,限制为4G
  • JVM中的堆不是为从磁盘上运行而设计的
  • 互换是有限的
如果您需要处理大数据,则需要使用BigMemory产品(EhCache或Terracotta)


最后,运行jvisualvm或使用
-verbose:gc
prameter查看堆分配。

一些您应该知道的事情

  • 托管内存交换不太好。事实上,这通常会导致应用程序死机或操作系统锁定(尤其是windows,即使10%的堆被交换,也必须关闭电源)
  • 堆被划分为多个区域,它不会像您预期的那样始终调整大小。通常情况下,它会将这些区域一起缩放,例如,它将使年轻空间和终身空间的比例为1:8,即,您无法轻松地一次抓取几乎所有的堆。我会尝试最大192 GB的堆
  • 大多数高级进程支持48位地址空间或256 TB虚拟内存,而实际内存仅为40位(每个处理器1 TB)
  • -d64
    仅适用于Solaris
简而言之,你需要大约256 GB的主内存和一个大堆,你真的在考虑你在做什么。随机访问内存比访问磁盘空间快100万倍,这意味着它不仅慢100万倍,而且根本不可能工作


你能做的就是使用堆外内存,如果你真的知道你在做什么,你可以让它工作,并且可能只比拥有你需要的内存慢100倍。esp如果您使用快速SSD进行交换或矩阵稀疏,则这是正确的方法。

数据类型和维度是什么?您可以显示声明吗?@user2357112请参阅edit给我们-Xms和-Xmx和-XX:MaxPermSize…@Shmoopy在这种情况下是的,如果您将硬盘的大部分设置为分页,您可以从磁盘中使用尽可能多的内容。@Shmoopy:您的进程没有2^64字节可用。它受到页面文件/交换空间大小的限制。你为此拨了多少钱?你到底在使用什么操作系统?注意
2048m
之后的
m
?这意味着兆字节。同样,您可以将
g
用于千兆字节,因此
16g
将意味着16GB,与
16384m
(16384兆字节)相同。是否有任何参考“JVM中的堆不是设计为从磁盘上运行的?”?这不是真正的规范,但取决于JVM实现。一般来说,高速运行的JVM需要连续的OS内存,而交换或32位操作系统不能保证这一点。