简体   繁体   English

JVM 出于 Memory 原因

[英]JVM Out of Memory Causes

Questions are based on Oracle Hotspot JDK8.问题基于Oracle Hotspot JDK8。

When applicaton come across java.lang.OutOfMemory: Java heap space exception, I suppose, where are two possible reasons.当应用程序遇到java.lang.OutOfMemory: Java heap space异常时,我想,其中有两个可能的原因。

  1. Allocated JVM heap size reaches -Xmx specified size and GC system cann't squeeze out enough space.分配的 JVM 堆大小达到-Xmx指定大小,GC 系统无法挤出足够的空间。
  2. Allocated JVM heap doesn't reach -Xmx , but there are not enough physical memory for JVM heap to grow.分配的 JVM 堆未达到-Xmx ,但没有足够的物理 memory 供 JVM 堆增长。 Suppose -Xms < -Xmx .假设-Xms < -Xmx

I know 1 is a reason for JVM to throw out java.lang.OutOfMemory: Java heap space exception.我知道1是 JVM 抛出java.lang.OutOfMemory: Java heap space异常的原因。 Is 2 a reasonable one cause? 2是一个合理的原因吗?

I find some articles mentioned java.lang.OutOfMemoryError: native memory exhausted , but they are all limited to IBM website.我发现有些文章提到java.lang.OutOfMemoryError: native memory exhausted ,但都仅限于IBM网站。 Is this expetion limited to IBM implemented JVM or it is a standard expetion in JVM Specification?此实验仅限于 IBM 实施的 JVM 还是 JVM 规范中的标准实验?


I did some experiments with code supplied by @Eugene in answer.我用@Eugene 在回答中提供的代码做了一些实验。 As @Holger noted the result varies in different environments.正如@Holger 指出的那样,结果在不同的环境中有所不同。 I tested in on both CentOS x64 and Win7 x64, with Hotspot JDK8 x64.我在 CentOS x64 和 Win7 x64 上使用 Hotspot JDK8 x64 进行了测试。 For simplicity swap and virtual memory are disabled.为简单起见,交换和虚拟 memory 被禁用。

I increase memory bound (-Xmx and -Xms) step by step.我逐步增加 memory 绑定(-Xmx 和 -Xms)。

I. -Xmx < available logic memory I.-Xmx <可用逻辑 memory

  • On both CentOS and Windows it shows OutOfMemoryError: Java heap space在 CentOS 和 Windows 上都显示OutOfMemoryError: Java heap space

II.二。 available logic memory < -Xmx < max physical memory可用逻辑 memory < -Xmx <最大物理 memory

  • CentOS: The GC try to Full GC serveral times, with Allocation Failure , and process be killed by system, leaving a message Killed . CentOS: GC 尝试 Full GC 几次,出现Allocation Failure ,并且进程被系统杀死,留下消息Killed
  • Windows: The GC try to Full GC serveral times, with Allocation Failure , and throw out OutOfMemoryError: Java heap space Windows:GC 尝试 Full GC 几次,分配失败,并抛出OutOfMemoryError:Java 堆空间

III.三、 -Xmx > max physical memory -Xmx >最大物理 memory

  • CentOS: same as in II CentOS:同II
  • Windows: same as in II Windows:同II

IV.四、 -Xms > max physical memory -Xms >最大物理 memory

  • CentOS: JVM seems fail to start. CentOS:JVM 似乎无法启动。 Error message is like:错误信息是这样的:

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

  • Windows: JVM failed to start. Windows:JVM 启动失败。 Error message is like:错误信息是这样的:

Error occurred during initialization of VM Could not reserve enough space for object heap VM 初始化期间发生错误 Could not reserved enough space for object heap


So, the same JVM behave differently in different OS.因此,相同的 JVM 在不同的操作系统中表现不同。

  • On windows, the OS doesn't kill JVM. And JVM always throw out OutOfMemoryError: Java heap space when memory usage grow exceeds.在 windows 上,操作系统不会杀死 JVM。当 memory 使用量增长超过时,JVM 总是抛出OutOfMemoryError: Java heap space
  • On Linux, the OS kill processes when there is not enough memory.在 Linux 上,当没有足够的 memory 时,操作系统会终止进程。
  • On both OS JVM failed to start when available memory doesn't satisfy JVM minimal requirement.在两个操作系统上,JVM 在可用时无法启动 memory 不满足 JVM 最低要求。

First of all there are more reasons for a GC to fail with "out of memory" as the comment under your question explains.首先,正如您问题下的评论所解释的那样,GC 因“内存不足”而失败的原因更多。

Proving point number (2) is easy, just create some code that always allocates:证明点数 (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());
}

And run this with -Xms1g -Xmx100g , on a system that has less then 100g of RAM.并在 RAM 少于100g的系统上使用-Xms1g -Xmx100g运行它。 You can enable GC logs (I did with "-Xlog:heap*=debug" "-Xlog:gc*=debug" in java-9 flags for example) and see how hard GC is trying to cope with this constant allocation, ultimately failing.您可以启用 GC 日志(例如,我在 java-9 标志中使用"-Xlog:heap*=debug" "-Xlog:gc*=debug" )并查看 GC 最终尝试处理这种常量分配的难度失败。

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

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