JDK-6534149 : ThreadGroup.uncaughtException needs to be more resilient to OutOfMemoryError
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2007-03-13
  • Updated: 2010-04-04
  • Resolved: 2007-03-14
Related Reports
Duplicate :  
Description
I recently helped investigate an apparent "hang" in using ScheduledThreadPoolExecutor that turned out to be caused by the main thread encountering an OutOfMemoryError and terminating without producing any sign that an exception had occurred.

The problem is that ThreadGroup.uncaughtException relies on being able to allocate memory to produce any output:

           } else if (!(e instanceof ThreadDeath)) {
		System.err.print("Exception in thread \""
				 + t.getName() + "\" ");
                e.printStackTrace(System.err);
            }

When memory is exhausted the string concatenation above will trigger a secondary OutOfMemoryError and so the thread will terminate silently.

There are a number of simple things that can be done to alleviate this problem:
- don't use String concatenation in the above
- check for OOME explicitly and report it directly rather than relying on printStackTrace

More sophisticated checking would place the printStackTrace in a try/catch and report if printing the stacktrace failed due to an exception.

Comments
SUGGESTED FIX A simple first cut: public void uncaughtException(Thread t, Throwable e) { if (parent != null) { parent.uncaughtException(t, e); } else { Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh != null) { ueh.uncaughtException(t, e); } else if (!(e instanceof ThreadDeath)) { // try to avoid allocation in case we're out-of-memory System.err.print("Exception in thread \""); System.err.print(t.getName()); System.err.print("\" "); // report OOME now in case printStackTrace also throws if (e instanceof OutOfMemoryError) { // use pre-allocated String literal System.err.println(OOME_MESSAGE); } e.printStackTrace(System.err); } } } static final String OOME_MESSAGE = "OutOfMemoryError occurred - stacktrace may be unavailable";
13-03-2007