'-XX:+ExitOnOutOfMemoryError ignored on 'java.lang.OutOfMemoryError: Direct buffer memory'

If the OutOfMemoryError is caused by allocating a direct byte buffer than the JVM flag -XX:+ExitOnOutOfMemoryError is ignored.

Checked on Oracle JDK and OpenJDK Java version "1.8.0_144" Java(TM) SE Runtime Environment (build 1.8.0_144-b01) Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

OS: Ubuntu 16.04

to reproduce run the following code

package com.company;
import java.nio.ByteBuffer;
public class Main {

    public static void main(String[] args) {
        // This should guarantee to throw:            
        try {
            ByteBuffer bb = ByteBuffer.allocateDirect(10485760*2);
            System.out.println("OOME not triggered");
        } catch (OutOfMemoryError err) {                
            System.out.println("OOME didn't terminate JVM!");
        }
    }
}

jvm args: -XX:MaxDirectMemorySize=10485760 -XX:+ExitOnOutOfMemoryError

The program outputs "OOME didn't terminate JVM!" and terminates with exit code 0. I expected it to crash and return exit code greater than 0. It works in this way when OutOfMemory is thrown due to low heap space.

If you run the following code with jvm args -Xmx10485760 -XX:+ExitOnOutOfMemoryError then the jvm process will crash with exit code 3:

try {        
    byte[] b = new byte[10485760*2];
    System.out.println("OOME not triggered");
} catch (OutOfMemoryError err) {
    System.out.println("OOME didn't terminate JVM!");
}

The output of the code above will be: Terminating due to java.lang.OutOfMemoryError: Java heap space And this is the expected behavior but that is not reproduced with the first example.

How to make ExitOnOutOfMemoryError option to work for this case? Maybe there is an updated JDK or alternative JDK implementation that doesn't have such bug?

I have this problem with druid.io. If real-time index task encounters

java.lang.OutOfMemoryError: Direct buffer memory

it hangs and doesn't terminate.



Solution 1:[1]

According to a discussion on the Java issue tracker, ExitOnOutOfMemoryError is only intended to cover OutOfMemory errors thrown by the JVM itself. NIO buffers are allocated from native code and so OOM errors related to them are also thrown from native code, so unfortunately this appears to be the intended behaviour.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Hal