views:

492

answers:

5

I have a thread in a Java web application that causes a java.lang.OutOfMemoryError: Java heap space exception, but the try/catch block does not catch the error.

Sample code:

private void doSomeWork()
{
     try
     {
         processData();  //Causes OutOfMemoryError
         System.out.println("This line does not execute");
     }
     catch (Exception e)
     {
         System.out.println("Exception.  This line does not execute.");
         //Log error
     }
     finally
     {
         System.out.println("finally.  This line does execute");
         System.out.println("Thread name: " + Thread.currentThread().getName());

     }
}

Output:

finally.  This line does execute 
Thread name: _Worker-8
Exception in thread "_Worker-8" java.lang.OutOfMemoryError: Java heap space
...

Background:

I recently took over this Java project and I'm trying to get up to speed with Java and this project. I'm a C# developer, so I'm not yet familiar with this project or Java. I know I can fix the error using the -Xmx setting, but I'm interested in catching this error so I can log it. The error is not showing up in any of the logs files, and the output is being shown in the console in debug mode in Eclipse.

+25  A: 

Because OutOfMemoryError is an Error, not an Exception. Since OutOfMemoryError isn't a subclass of Exception, the catch (Exception e) doesn't apply.

OutOfMemoryError does extend Throwable, however, so you should be able to catch it. Here's a SO discussion on when (if ever) you should catch Errors. Generally, since you can't do anything about it, the recommendation is to not bother catching Errors in production code. But given a special case where you're trying to debug what's going on, it might be helpful.

Kaleb Brasee
Nice Answer with link references. I appreciate it, Thanks!
Chris Persichetti
I would recommend catching throwables in the most outer part of your application (or in the most outer part of a thread method) so you can actually know why your program has aborted (if there's no one else that is going to do that for you).
Ravi Wallau
+3  A: 

"~Error" are not "~Exception".

You have to catch "Error" or "Throwable"

Dennis Cheung
+2  A: 

OutOfMemoryError extends VirtualMachineError while Exception extends Throwable directly. So it is not being caught as per Java specs. IF you're looking to catch all exceptions, add catch (Throwable e) to the clause and you'll have it.

Daniil
to be more precise, OutOfMemoryError extends VirtualMachineError, which extends Error, and since Errors are not Exceptions, a catch(Exception) cannot catch it
chburd
Bingo. Thought to list the whole tree but got lazy :)
Daniil
+8  A: 

java.lang.OutOfMemoryError doesn't extends java.lang.Exception so it's not an Exception. OutOfMemoryError extends java.lang.Error. If you want to catch Error try this:

private void doSomeWork()
{
     try
     {
         processData();  //Causes OutOfMemoryError
         System.out.println("This line does not execute");
     }
     catch (Error e)
     {
         System.out.println("Exception.  This line does not execute.");
         //Log error
     }
     finally
     {
         System.out.println("finally.  This line does execute");
         System.out.println("Thread name: " + Thread.currentThread().getName());

     }
}

Note: Exception and Error extends Throwable so you you can also use Throwable to catch both.

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Throwable.html

Massimo Fazzolari
A: 

What I will usually do is add an 'UncaughtExceptionHandler' to a Thread so if anything leaks by you at least have a chance to log the issue and maybe do some cleanup.

Javamann