当前位置: 首页 > 知识库问答 >
问题:

JVM内存不足的原因

司空浩邈
2023-03-14

问题基于Oracle Hotspot JDK8。

我想,当应用程序遇到Java.lang.OutOfMemory:Java堆空间异常时,可能有两个原因。

  1. 分配的JVM堆大小达到-xmx指定大小,GC系统无法挤出足够的空间。
  2. 分配的JVM堆没有到达-xmx,但是没有足够的物理内存使JVM堆增长。假设-xms<-xmx.

我用@Eugene在Answer中提供的代码做了一些实验。正如@Holger所指出的,结果在不同的环境中有所不同。我使用Hotspot JDK8 x64在CentOS x64和Win7 x64上进行了测试。为了简单起见,禁用了交换和虚拟内存。

我逐步增加内存边界(-xmx和-xms)。

I.-XMX<可用逻辑存储器

    null
    null

iii.-xmx>最大物理内存

  • CentOS:与II中相同
  • Windows:与II中相同

iv.-XMS>最大物理内存

  • CentOS:JVM似乎无法启动。错误消息如下:

Java HotSpot(TM)64位服务器VM警告:info:os::commit_memory(0x00000000E62A0000,349569024,0)失败;错误=“无法分配内存”(errno=12)

    null

因此,相同的JVM在不同的操作系统中表现不同。

  • 在windows上,操作系统不会终止JVM。和JVM总是抛出OutOfMemoryError:Java堆空间。
  • 在Linux上,当内存不足时,OS会终止进程。
  • 当可用内存不满足JVM的最低要求时,两个OS上的JVM都无法启动。

共有1个答案

松新
2023-03-14

首先,有更多的原因导致GC以“内存不足”失败,正如您的问题下面的注释所解释的。

证明点编号(2)很容易,只需创建一些始终分配的代码:

public static void main(String[] args) {
    test(1);
}

static void test(int x){
    List<byte[]> list = new ArrayList<>();
    while(x == 1){
        byte [] b =new byte[1 * 1024 * 1024];
        b[100] = 42;
        list.add(b);
    }

    System.out.println(list.hashCode());
}

并使用-xms1g-xmx100g在RAM小于100g的系统上运行。您可以启用GC日志(例如,我在java-9标志中使用“-xlog:heap*=debug”“-xlog:GC*=debug”)并查看GC如何努力处理这种常量分配,但最终还是失败了。

 类似资料:
  • 我一直在使用G1垃圾收集器经历Java VM崩溃。我们得到使用以下签名生成的hs_err_pid.log文件:

  • 问题内容: 我在自己的环境中不断检测PermGen中的OOM: Java 6的 jboss-4.2.3 网络应用程序不大 我知道String.intern()问题-但是我没有足够有价值的用法。MaxPermGen大小的增加并没有费力(从128 Mb到256 Mb)。 还有什么其他原因可以为PermGen调用OOM?在这种情况下(策略,工具等)哪种调查方案是最佳的? 谢谢你的帮助 问题答案: 看到这

  • 问题内容: 我使用io.Copy()复制文件,大约700Mb,但这会导致内存不足 错误信息如下: 我为buf分配了足够的内存,这导致bodyWriter.CreateFormFile()中的内存不足 问题答案: 这是因为您正在“复制”到,这是内存中的缓冲区,从而迫使Go尝试分配与整个文件一样大的内存块。 根据您的使用情况,您似乎正在尝试通过HTTP流式传输文件?在这种情况下,请勿将传递给,而是直接

  • 我正在努力解决古老的字谜问题。多亏了许多教程,我能够迭代一组字符串,递归地找到所有的排列,然后将它们与英语单词列表进行比较。我发现的问题是,在大约三个单词之后(通常是关于“变形”之类的东西),我会得到一个OutOfMemory错误。我试着把我的批分成小的集合,因为它似乎是消耗我所有内存的递归部分。但即使只是“变形”也把它锁起来了... 编辑:根据出色的反馈,我已经将生成器从排列更改为工作查找: 它

  • 问题内容: 我正在研究真正了解JVM中内存分配的工作方式。我正在编写一个内存不足的应用程序:堆空间异常。 我知道我可以传入VM参数(例如Xms和Xmx)来增加JVM为正在运行的进程分配的堆空间。这是解决此问题的一种可能的解决方案,或者我可以检查代码是否存在内存泄漏并在那里解决问题。 我的问题是: 1)JVM如何实际为其分配内存?这与OS如何将可用内存传递给JVM有什么关系?或更一般而言,任何进程的

  • 我想真正了解内存分配在JVM中是如何工作的。我正在编写一个内存不足的应用程序:堆空间异常。 我知道我可以传入VM参数,如Xms和Xmx,以增加JVM为正在运行的进程分配的堆空间。这是一个可能的解决方案,或者我可以检查我的代码内存泄漏并修复那里的问题。 我的问题是: 1)JVM实际上如何为自己分配内存?这与OS如何将可用内存传递给JVM有什么关系?或者更一般地说,为任何进程分配内存实际上是如何工作的