【发布时间】:2020-12-09 08:30:57
【问题描述】:
问题基于 Oracle Hotspot JDK8。
当应用程序遇到java.lang.OutOfMemory: Java heap space 异常时,我想,有两个可能的原因。
- 分配的 JVM 堆大小达到
-Xmx指定大小,GC 系统无法挤出足够的空间。 - 分配的 JVM 堆未达到
-Xmx,但没有足够的物理内存供 JVM 堆增长。假设-Xms-Xmx。
我知道1 是JVM 抛出java.lang.OutOfMemory: Java heap space 异常的原因。 2 是一个合理的原因吗?
我发现some articles 提到了java.lang.OutOfMemoryError: native memory exhausted,但它们都仅限于IBM 网站。 此扩展仅限于 IBM 实现的 JVM 还是 JVM 规范中的标准扩展?
我用@Eugene 提供的代码做了一些实验。正如@Holger 所指出的,结果因环境而异。我使用 Hotspot JDK8 x64 在 CentOS x64 和 Win7 x64 上进行了测试。 为简单起见,已禁用交换和虚拟内存。
我逐步增加内存限制(-Xmx 和 -Xms)。
我。 -Xmx 可用的逻辑内存
- 在 CentOS 和 Windows 上都显示 OutOfMemoryError: Java heap space
二。 可用逻辑内存 最大物理内存
- CentOS:GC 多次尝试 Full GC,Allocation Failure,进程被系统杀死,并留下消息Killed。
- Windows:GC 多次尝试 Full GC,Allocation Failure,并抛出 OutOfMemoryError: Java heap space
三。 -Xmx > 最大物理内存
- CentOS:与 II 相同
- Windows:与 II 中相同
四。 -Xms > 最大物理内存
- CentOS:JVM 似乎无法启动。错误信息如下:
Java HotSpot(TM) 64 位服务器虚拟机警告:INFO: os::commit_memory(0x00000000e62a0000, 349569024, 0) 失败; error='无法分配内存' (errno=12)
- Windows:JVM 无法启动。错误信息如下:
虚拟机初始化过程中发生错误 无法为对象堆保留足够的空间
因此,相同的 JVM 在不同的操作系统中表现不同。
- 在 Windows 上,操作系统不会杀死 JVM。并且当内存使用增长超过时,JVM总是抛出OutOfMemoryError: Java heap space。
- 在 Linux 上,当内存不足时,操作系统会终止进程。
- 在两个操作系统上,当可用内存不能满足 JVM 最低要求时,JVM 无法启动。
【问题讨论】:
-
你为什么不试试看看会发生什么?将
-Xmx设置为超过您计算机上的虚拟空间,然后运行一个分配空间的程序,直到它终止。 --- 提示: 在虚拟机或 Docker 中运行它可能更容易,您可以更好地控制“机器”有多少内存。 -
这取决于特定环境(包括JVM实现)a)
-Xmx是否需要物理内存(而不是逻辑内存/交换空间)和b)它允许指定比系统更多的最大内存可以处理。甚至还有那个臭名昭著的 Linux 内存过度使用特性,即它保证了内存的可用性,因为分配请求永远不会失败,但它只是在内存不足时随机杀死进程。 -
@Holger 我记得
-Xmx,目前,将“提交”那么多内存,但还没有驻留。至于第(2)点:每个处理容器的java人员,尤其是kubernetes都应该意识到这种突然死亡,特别是因为它不支持swap。优秀的 cmets。 -
@Andreas 我试过了,它似乎在情况 2 中被系统杀死了