Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JVM内存不足的原因_Java_Jvm - Fatal编程技术网

Java JVM内存不足的原因

Java JVM内存不足的原因,java,jvm,Java,Jvm,问题基于Oracle热点JDK8 当应用程序遇到java.lang.OutOfMemory:java堆空间异常时,我想可能有两个原因 分配的JVM堆大小达到指定的大小,GC系统无法挤出足够的空间 分配的JVM堆未达到-Xmx,但没有足够的物理内存供JVM堆增长。假设-Xms-Xmx 我知道1是JVM抛出java.lang.OutOfMemory:java堆空间异常的原因是2一个合理的原因吗? 我发现前面提到的java.lang.OutOfMemoryError:本机内存耗尽,但它们都限于IBM网

问题基于Oracle热点JDK8

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

  • 分配的JVM堆大小达到指定的大小,GC系统无法挤出足够的空间
  • 分配的JVM堆未达到
    -Xmx
    ,但没有足够的物理内存供JVM堆增长。假设
    -Xms
    -Xmx
  • 我知道
    1
    是JVM抛出
    java.lang.OutOfMemory:java堆空间
    异常的原因
    2
    一个合理的原因吗?

    我发现前面提到的
    java.lang.OutOfMemoryError:本机内存耗尽
    ,但它们都限于IBM网站此体验仅限于IBM实现的JVM,还是JVM规范中的标准体验?


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

    我逐步增加内存限制(-Xmx和-Xms)

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

    • 在CentOS和Windows上,它都显示了OutOfMemoryError:Java堆空间
    二,。可用逻辑内存<-Xmx<最大物理内存

    • CentOS:GC尝试完成GC服务器时间,分配失败,进程将被系统终止,并留下一条消息killed
    • Windows:GC尝试满GC服务器时间,但分配失败,并抛出OutOfMemoryError:Java堆空间
    三、 -Xmx>最大物理内存

    • CentOS:与第二版相同
    • Windows:与II中的相同
    四、 -Xms>最大物理内存

    • CentOS:JVM似乎无法启动。错误消息如下所示:
    Java HotSpot(TM)64位服务器VM警告:信息:os::提交_内存(0x00000000e62a0000,349569024,0)失败;错误=“无法分配内存”(errno=12)

    • Windows:JVM无法启动。错误消息如下所示:
    初始化VM时出错 无法为对象堆保留足够的空间


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

    • 在windows上,操作系统不会杀死JVM。而且当内存使用量增长超过时,JVM总是抛出OutOfMemoryError:Java堆空间
    • 在Linux上,当内存不足时,操作系统会终止进程
    • 在两个操作系统上,当可用内存不满足JVM最低要求时,JVM无法启动

    首先,正如您的问题下面的注释所解释的,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());
    }
    
    publicstaticvoidmain(字符串[]args){
    试验(1);
    }
    静态孔隙试验(int x){
    列表=新的ArrayList();
    而(x==1){
    字节[]b=新字节[1*1024*1024];
    b[100]=42;
    列表.添加(b);
    }
    System.out.println(list.hashCode());
    }
    

    并在内存小于
    100g
    的系统上,使用
    -Xms1g-Xmx100g
    运行此程序。您可以启用GC日志(例如,我在java-9标志中使用了
    “-Xlog:heap*=debug”“-Xlog:GC*=debug”
    ),并查看GC如何努力处理这个常量分配,最终失败。

    为什么不尝试一下,看看会发生什么?将
    -Xmx
    设置为超过计算机上的虚拟空间,然后运行一个分配空间的程序,直到它消失提示:在虚拟机或Docker中运行可能更容易,您可以更好地控制“机器”的内存量。请参阅这取决于特定环境(包括JVM实现)a)
    -Xmx是否需要物理内存(而不是逻辑内存/交换空间)和b)它允许指定系统无法处理的最大内存。甚至还有一个臭名昭著的Linux超量使用内存的功能,即它保证了内存的可用性,因为分配请求永远不会失败,但它只是在内存不足时随机终止进程。@Holger根据我记忆中的
    -Xmx
    ,目前将“提交”那么多内存,而这些内存还不是驻留的。关于第(2)点:每个处理容器的java人员,特别是kubernetes,都应该意识到这种突然死亡,特别是因为它不支持交换。非常好的评论。@Andreas我试过,在第二种情况下,我在CentOS上用JDK8(交换关闭)试过,似乎被系统杀死了。当-Xmx大于pyhsical内存时,它会被系统杀死,JVM会消耗所有可用内存,只留下一条消息被杀死。那么它是否证明了我显示了OutOfMemoryError:Java堆空间,它不可能是原因2?@SuN有趣。在我的mac电脑上,它会随着OOM一起消失。您是否在容器中运行此测试?不,我使用CentOS和Windows 7作为来宾操作系统在VirtualBox中运行测试。更多详细信息请参见问题描述第二节“实验”。您可以通过VirtualBox在虚拟化容器中运行。你所看到的一切都是意料之中的。