Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

java

jvm

nio

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.

like image 883
denisvlah Avatar asked May 08 '18 11:05

denisvlah


1 Answers

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.

  • The behaviour is discussed in this issue: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8257790
  • Another issue requests that more detail to the ExitOnOutOfMemoryError description: https://bugs.openjdk.java.net/browse/JDK-8258058
    • This is the commit that adds extra detail — it limits the OOM Errors handled to those that are thrown from the JVM: https://github.com/openjdk/jdk/commit/0c8cc2cd
like image 77
Hal Avatar answered Nov 15 '22 14:11

Hal