JDK-8155004 : CrashOnOutOfMemoryError doesn't work for OOM caused by inability to create threads
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 8,9
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: linux
  • CPU: x86_64
  • Submitted: 2016-04-20
  • Updated: 2019-01-24
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

FULL OS VERSION :
Linux xxxxx 4.0.9 #1 SMP Fri Feb 26 15:21:14 PST 2016 x86_64 x86_64 x86_64 GNU/Linux
Darwin xxxxx 15.4.0 Darwin Kernel Version 15.4.0: Fri Feb 26 22:08:05 PST 2016; root:xnu-3248.40.184~3/REL

A DESCRIPTION OF THE PROBLEM :
The newly introduced CrashOnOutOfMemoryError option doesn't appear to work when the cause of the OOM is due to not being able to create new threads.

THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Did not try

THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Did not try

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the program below with "java -XX:+CrashOnOutOfMemoryError Test". After a few seconds, an OutOfMemoryError (unable to create new native thread) will be printed to the console but the program won't exit.

EXPECTED VERSUS ACTUAL BEHAVIOR :
I would expect the VM to crash, but it keeps running.
REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
class Test {
    public static void main(String[] args)
            throws InterruptedException
    {
        Thread t = new Thread(() -> {
            while (true) {
                new Thread(() -> {
                    try {
                        Thread.currentThread().join();
                    }
                    catch (InterruptedException e) {
                    }
                }).start();
            }
        });

        t.start();
        Thread.currentThread().join();
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Use a JVMTI agent to intercept ResourceExhausted events and forcibly exit the VM (e.g., https://github.com/airlift/jvmkill)


Comments
After exploring the code base I have found there are many types of OutOfMemoryError. 1. java.lang.OutOfMemoryError: Java heap space This error will be triggered when the application attempts to add more data into the heap space area, but there is not enough room for it. Note that there might be plenty of physical memory available, but the java.lang.OutOfMemoryError: Java heap space error is thrown whenever the JVM reaches the heap size limit. 2. java.lang.OutOfMemoryError: GC overhead limit exceeded This error means that the GC tried to free memory but was pretty much unable to get anything done. By default it happens when the JVM spends more than 98% of the total time in GC and when after GC less than 2% of the heap is recovered. 3. java.lang.OutOfMemoryError: Metaspace/Compressed class space Main cause for the this error is either too many classes or too big classes being loaded to the Metaspace. 4. java.lang.OutOfMemoryError: Unable to create new native thread Whenever the underlying OS cannot allocate a new native thread, this OutOfMemoryError will be thrown. The exact limit for native threads is very platform-dependent 5. java.lang.OutOfMemoryError: Out of swap space? This error is thrown by JVM when an allocation request for bytes from the native heap fails and the native heap is close to exhaustion. It is often caused by operating system level issues, such as: a. The operating system is configured with insufficient swap space. b. Another process on the system is consuming all memory resources. 6. java.lang.OutOfMemoryError: Requested array size exceeds VM limit This means that the application that crashes with the error is trying to allocate an array larger than the Java Virtual Machine can support
01-08-2016

I believe we should simply add the check for "OnOutOfMemory" flags to when we fail to allocate native threads. If you do see this failure and you add any of these flags, it probably is because you want to debug that issue. According to David, this is not fixed in 9, but the test itself is somewhat non-deterministic as it depends on how we run out of memory first.
02-05-2016

I would not expect this to work fine in 9-b115 as we do not invoke the code that checks CrashOnOutOfMemoryError when we fail to allocate a native thread - we simply do: THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), os::native_thread_creation_failed_msg());
26-04-2016

This works fine with windows and doesn't work well with linux, Even after throwing exception, program is still running, required to press contr+C to come out. -sh-4.1$ /opt/java/jdk1.8.0_92/bin/java -Xmx2048k -Xms2048k -XX:+CrashOnOutOfMemoryError Test Exception in thread "Thread-0" java.lang.OutOfMemoryError: unable to create new native thread at java.lang.Thread.start0(Native Method) at java.lang.Thread.start(Thread.java:714) at Test.lambda$main$1(Test.java:13) at java.lang.Thread.run(Thread.java:745) ^C-sh-4.1$
25-04-2016