446
votes

In C#, I can use the throw; statement to rethrow an exception while preserving the stack trace:

try
{
   ...
}
catch (Exception e)
{
   if (e is FooException)
     throw;
}

Is there something like this in Java (that doesn't lose the original stack trace)?

9
Why do you think it looses the original stacktrace? The only way to loose it when you throw new SomeOtherException and forget to assign the root cause in the constructor or in initCause(). - akarnokd
I believe this is how the code behaves in .Net, but I'm no longer positive. It might be worthwhile to either look it up somewhere or run a small test. - ripper234
Throwables don't get modified by throwing them. To update the stack trace you have to call fillInStackTrace(). Conveniently this method gets called in the constructor of a Throwable. - Robert
In C#, yes, throw e; will lose the stacktrace. But not in Java. - Tim Goodman

9 Answers

608
votes
catch (WhateverException e) {
    throw e;
}

will simply rethrow the exception you've caught (obviously the surrounding method has to permit this via its signature etc.). The exception will maintain the original stack trace.

83
votes

I would prefer:

try
{
    ...
}
catch (FooException fe){
   throw fe;
}
catch (Exception e)
{
    // Note: don't catch all exceptions like this unless you know what you
    // are doing.
    ...
}
81
votes

You can also wrap the exception in another one AND keep the original stack trace by passing in the Exception as a Throwable as the cause parameter:

try
{
   ...
}
catch (Exception e)
{
     throw new YourOwnException(e);
}
22
votes

In Java is almost the same:

try
{
   ...
}
catch (Exception e)
{
   if (e instanceof FooException)
     throw e;
}
14
votes

In Java, you just throw the exception you caught, so throw e rather than just throw. Java maintains the stack trace.

6
votes

something like this

try 
{
  ...
}
catch (FooException e) 
{
  throw e;
}
catch (Exception e)
{
  ...
}
5
votes
public int read(byte[] a) throws IOException {
    try {
        return in.read(a);
    } catch (final Throwable t) {
        /* can do something here, like  in=null;  */
        throw t;
    }
}

This is a concrete example where the method throws an IOException. The final means t can only hold an exception thrown from the try block. Additional reading material can be found here and here.

3
votes

Stack trace is prserved if you wrap the catched excetion into an other exception (to provide more info) or if you just rethrow the catched excetion.

try{ ... }catch (FooException e){ throw new BarException("Some usefull info", e); }

2
votes

I was just having a similar situation in which my code potentially throws a number of different exceptions that I just wanted to rethrow. The solution described above was not working for me, because Eclipse told me that throw e; leads to an unhandeled exception, so I just did this:

try
{
...
} catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {                    
    throw new RuntimeException(e.getClass().getName() + ": " + e.getMessage() + "\n" + e.getStackTrace().toString());
}

Worked for me....:)