带有HotSpot VM的Java SE
6报价故障排除指南
3.1.3详细信息:(行
Requested array size exceeds VM limit内粗体为我的):详细消息
Requested array size exceeds VMlimit表明应用程序(或该应用程序使用的API)尝试分配大于堆大小的数组。例如,如果应用程序尝试分配512MB的数组,但最大堆大小为256MB,OutOfMemoryError则将抛出原因Requestedarray size exceeds VM limit。在大多数情况下,问题可能是 配置问题 (堆大小太小),或者
是导致应用程序尝试创建大数组的错误 ,例如,当使用计算算法来计算数组中的元素数时尺寸不正确。
更新:在 @Pacerier的 鼓励下,我进行了一些快速测试。我编写了一个示例程序:
public class VmLimitTest { public static final int SIZE = 2; public static void main(String[] args) throws InterruptedException { while(true) { byte[] a = new byte[SIZE * 1024 * 1024]; TimeUnit.MILLISECONDS.sleep(10); } }}
并使用以下JVM选项运行它:
-Xms192m -Xmx192m -XX:NewRatio=2 -XX:SurvivorRatio=6 -XX:+PrintGCDetails
这是他们的意思:
- 整个堆为192 MiB(
-Xms192m -Xmx192m
) - 年轻一代(eden +幸存者)空间为64 MiB,老一代为128 MiB(
-XX:NewRatio=2
) - 每个幸存者空间(两个)为8 MiB,因此伊甸园剩下48 MiB(比率为1:6
-XX:SurvivorRatio=6
)
在测试时,我发现了以下内容:
- 如果新创建的数组可以放入eden(小于48 MiB),则程序运行正常
- 令人惊讶的是,当数组大小超过eden大小,但可以放入eden和 一个 幸存者空间(介于48和56 MiB之间)时,JVM可以在eden和Survivor上分配单个对象(重叠两个区域)。整齐!
- 一旦阵列大小超过eden +单个幸存者(高于56 MiB),新创建的对象将绕过eden和幸存者空间而直接放置在旧世代中。这也意味着突然之间一直在执行完整的GC-非常糟糕!
- 我可以轻松分配127 MiB的数据,但是尝试分配129 MiB 会抛出 异常
OutOfMemoryError: Java heap space
这是底线-您不能创建尺寸大于上一代的对象。尝试这样做将导致
OutOfMemoryError: Java heapspace错误。那么,我们
Requested array size exceeds VM limit什么时候可以期望可怕呢?
我尝试使用更大的对象运行同一程序。达到阵列长度限制后,我切换到
long[]了该端口,可以轻松达到7 GiB。使用128
MiB的最大堆声明了JVM仍在抛出
OutOfMemoryError: Java heapspace(!),我设法触发
OutOfMemoryError: Requested array size exceeds VMlimit错误,试图在单个对象中分配8 GiB。我在具有3 GiB物理内存和1 GiB交换的32位Linux计算机上对此进行了测试。
话虽这么说,您可能永远都不会遇到此错误。该文档似乎不准确/已过时,但确实有一个结论: 这可能是一个错误, 因为创建如此大的数组非常罕见。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)