繁体   English   中英

JVM 出于 Memory 原因

[英]JVM Out of Memory Causes

问题基于Oracle Hotspot JDK8。

当应用程序遇到java.lang.OutOfMemory: Java heap space异常时,我想,其中有两个可能的原因。

  1. 分配的 JVM 堆大小达到-Xmx指定大小,GC 系统无法挤出足够的空间。
  2. 分配的 JVM 堆未达到-Xmx ,但没有足够的物理 memory 供 JVM 堆增长。 假设-Xms < -Xmx

我知道1是 JVM 抛出java.lang.OutOfMemory: Java heap space异常的原因。 2是一个合理的原因吗?

我发现有些文章提到java.lang.OutOfMemoryError: native memory exhausted ,但都仅限于IBM网站。 此实验仅限于 IBM 实施的 JVM 还是 JVM 规范中的标准实验?


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

我逐步增加 memory 绑定(-Xmx 和 -Xms)。

I.-Xmx <可用逻辑 memory

  • 在 CentOS 和 Windows 上都显示OutOfMemoryError: Java heap space

二。 可用逻辑 memory < -Xmx <最大物理 memory

  • CentOS: GC 尝试 Full GC 几次,出现Allocation Failure ,并且进程被系统杀死,留下消息Killed
  • Windows:GC 尝试 Full GC 几次,分配失败,并抛出OutOfMemoryError:Java 堆空间

三、 -Xmx >最大物理 memory

  • CentOS:同II
  • Windows:同II

四、 -Xms >最大物理 memory

  • CentOS:JVM 似乎无法启动。 错误信息是这样的:

Java HotSpot(TM) 64 位服务器 VM 警告:信息:os::commit_memory(0x00000000e62a0000, 349569024, 0) 失败; error='无法分配内存' (errno=12)

  • Windows:JVM 启动失败。 错误信息是这样的:

VM 初始化期间发生错误 Could not reserved enough space for object heap


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

  • 在 windows 上,操作系统不会杀死 JVM。当 memory 使用量增长超过时,JVM 总是抛出OutOfMemoryError: Java heap space
  • 在 Linux 上,当没有足够的 memory 时,操作系统会终止进程。
  • 在两个操作系统上,JVM 在可用时无法启动 memory 不满足 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());
}

并在 RAM 少于100g的系统上使用-Xms1g -Xmx100g运行它。 您可以启用 GC 日志(例如,我在 java-9 标志中使用"-Xlog:heap*=debug" "-Xlog:gc*=debug" )并查看 GC 最终尝试处理这种常量分配的难度失败。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM