Java JVM内存不足的原因
问题基于Oracle热点JDK8 当应用程序遇到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网
java.lang.OutOfMemory:java堆空间
异常时,我想可能有两个原因
-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堆空间
- CentOS:GC尝试完成GC服务器时间,分配失败,进程将被系统终止,并留下一条消息killed
- Windows:GC尝试满GC服务器时间,但分配失败,并抛出OutOfMemoryError:Java堆空间
- CentOS:与第二版相同
- Windows:与II中的相同
- CentOS:JVM似乎无法启动。错误消息如下所示:
- Windows:JVM无法启动。错误消息如下所示:
因此,相同的JVM在不同的操作系统中表现不同
- 在windows上,操作系统不会杀死JVM。而且当内存使用量增长超过时,JVM总是抛出OutOfMemoryError:Java堆空间
- 在Linux上,当内存不足时,操作系统会终止进程
- 在两个操作系统上,当可用内存不满足JVM最低要求时,JVM无法启动
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在虚拟化容器中运行。你所看到的一切都是意料之中的。