JVM Out of Memory Causes

Viewed 2157

Questions are based on Oracle Hotspot JDK8.

When applicaton come across java.lang.OutOfMemory: Java heap space exception, I suppose, where are two possible reasons.

  1. Allocated JVM heap size reaches -Xmx specified size and GC system cann't squeeze out enough space.
  2. Allocated JVM heap doesn't reach -Xmx, but there are not enough physical memory for JVM heap to grow. Suppose -Xms < -Xmx.

I know 1 is a reason for JVM to throw out java.lang.OutOfMemory: Java heap space exception. Is 2 a reasonable one cause?

I find some articles mentioned java.lang.OutOfMemoryError: native memory exhausted, but they are all limited to IBM website. Is this expetion limited to IBM implemented JVM or it is a standard expetion in JVM Specification?


I did some experiments with code supplied by @Eugene in answer. As @Holger noted the result varies in different environments. I tested in on both CentOS x64 and Win7 x64, with Hotspot JDK8 x64. For simplicity swap and virtual memory are disabled.

I increase memory bound (-Xmx and -Xms) step by step.

I. -Xmx < available logic memory

  • On both CentOS and Windows it shows OutOfMemoryError: Java heap space

II. available logic memory < -Xmx < max physical memory

  • CentOS: The GC try to Full GC serveral times, with Allocation Failure, and process be killed by system, leaving a message Killed.
  • Windows: The GC try to Full GC serveral times, with Allocation Failure, and throw out OutOfMemoryError: Java heap space

III. -Xmx > max physical memory

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

IV. -Xms > max physical memory

  • CentOS: JVM seems fail to start. Error message is like:

Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000e62a0000, 349569024, 0) failed; error='Cannot allocate memory' (errno=12)

  • Windows: JVM failed to start. Error message is like:

Error occurred during initialization of VM Could not reserve enough space for object heap


So, the same JVM behave differently in different OS.

  • On windows, the OS doesn't kill JVM. And JVM always throw out OutOfMemoryError: Java heap space when memory usage grow exceeds.
  • On Linux, the OS kill processes when there is not enough memory.
  • On both OS JVM failed to start when available memory doesn't satisfy JVM minimal requirement.
1 Answers

First of all there are more reasons for a GC to fail with "out of memory" as the comment under your question explains.

Proving point number (2) is easy, just create some code that always allocates:

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. 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.

Related