最后我知道在Sun的JVM中,必须在连续的地址空间中分配整个堆。我想对于大堆值,很难在启动后将其添加到您的地址空间中,同时又要确保它保持连续。您可能需要在启动时获取它,或者根本不需要。因此,它是固定的。
即使不是立即全部使用,启动时也会保留整个堆的地址空间。如果它不能为传递的-
Xmx值保留足够大的连续地址空间块,它将无法启动。这就是为什么很难在32位Windows上分配大于1.4GB的堆的原因-
因为很难找到该大小或更大大小的连续地址空间,因为某些DLL喜欢在某些地方加载,从而使地址空间碎片化。当您使用64位时,这并不是真正的问题,因为有更多的地址空间。
这几乎可以肯定是出于性能方面的考虑。我找不到很棒的链接来详细说明这一点,但是这是我在搜索时找到的彼得·凯斯勒(Peter
Kessler)的一个不错的报价(完整链接
-请务必阅读评论)。我相信他在Sun的JVM上工作。
之所以需要为堆使用连续的内存区域,是因为我们有一堆副数据结构,这些数据结构从堆开始处按(缩放的)偏移量进行索引。例如,我们使用“卡片标记数组”跟踪对象引用更新,该“卡片标记数组”每512字节堆有一个字节。当我们将引用存储在堆中时,我们必须在卡标记数组中标记相应的字节。我们右移商店的目标地址,并用它来索引卡标记阵列。用C
++玩(必须:-)玩Java不能解决的有趣的算术游戏。
那是在2004年-我不确定此后发生了什么变化,但是我很确定它仍然成立。如果您使用诸如Process
Explorer之类的工具,则可以看到Java应用程序的虚拟大小(添加虚拟大小和私有大小内存列)从启动时就包括了总堆大小(无疑还有其他所需的空间)。
,即使该进程“使用”的内存在堆开始填满之前也离它不远…
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)