502

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)?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
ripper234
  • 222,824
  • 274
  • 634
  • 905
  • 5
    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 Jul 08 '09 at 12:34
  • 5
    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 Jul 08 '09 at 15:03
  • 13
    `Throwable`s 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 Jul 27 '12 at 00:17
  • 62
    In C#, yes, `throw e;` will lose the stacktrace. But not in Java. – Tim Goodman Apr 22 '13 at 13:42
  • Some doc from Oracle about exceptions with Java 7 : [Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking](http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html) – Guillaume Husta Jul 08 '14 at 08:47

9 Answers9

676
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.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
  • 4
    Hi, InterruptedException e gives an unhandled Exception message when I add the throw e line. Not so if I replace it with the broader Exception e. How should this be done properly? – James P. Oct 31 '11 at 02:07
  • 1
    @James, I just observed that the message goes away if adding "throws XxxException" in function declaration. – shiouming Oct 13 '12 at 10:58
  • 2
    In Java 7 compiler for such rethrow is more inteligent. Now it works fine with specific "throws" exceptions in containing method. – Waldemar Wosiński Jan 29 '13 at 16:18
  • 238
    @James If you `catch(Exception e) { throw e; }` that will be unhandled. If you `catch(InterruptedException ie) { throw ie; }` it will be handled. As a rule of thumb, don't `catch(Exception e)` - this isn't pokemon, and we don't want to catch 'em all! – corsiKa Jun 10 '13 at 19:24
  • 1
    I see some code like this in a java project I'm working on - is it a no-op and safe to delete? – JonnyRaa May 30 '14 at 09:05
  • @JonnyLeeds If that is a try-with-resources statement, you should not delete it. – Nier Aug 31 '16 at 08:19
  • 13
    @corsiKa It's not necessarily true that you don't want to "Catch 'em all", it's just a different use case. If you have a top-level loop or event handler (for instance, inside a thread's run) if you don't catch at least RuntimeException and log it, you will often miss the exception altogether AND silently break out of an important loop for what is often a one-time failure. It's also really good for plugin functionality where you don't know what additional code might do or throw... For top-down uses like these catching Exception is often not only a good idea but a best practice. – Bill K Sep 30 '16 at 23:48
  • 1
    @BillK Um, sure. But that top level loop will really be handled by a high level framework, usually. Your typical developer will rarely be writing at that kind of level and if they are, they know when rules of thumbs need to be ignored. – corsiKa Oct 01 '16 at 02:22
  • 2
    @CorsiKa I mentioned it because the app I work on had a few threads that were randomly eating exceptions. Any thread you don't want to break out of silently should have a catch Exception at the top, and you might want to consider that there are a lot of developers who aren't in your exact situation--many programmers work with threads, not all use frameworks to abstract them--and some write their own frameworks. – Bill K Oct 01 '16 at 18:31
  • I think it's worth mentioning that it may not be "obvious" to someone learning Java that the surrounding method must permit re-throwing the exception. `surroundingMethod() throws WhateverException { ... }` – Bash Jul 01 '18 at 23:02
89

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);
}
Justin Ohms
  • 3,334
  • 31
  • 45
Olvagor
  • 2,332
  • 5
  • 25
  • 26
  • 13
    I would also advise on adding a message alongside, using `throw new YourOwnException("Error while trying to ....", e);` – Julien Mar 30 '17 at 09:19
  • this is what I was looking for, especially the version from the first comment where you can pass your own message – Csa77 Apr 14 '19 at 19:31
  • 4
    This show the error message correctly but the stack trace shows the error line as line with 'throw new.......(e)' not the original line that caused exception. – Ashburn RK May 18 '20 at 15:26
  • This only works if `YourOwnException` is properly set up, see the 4 public constructors on `RuntimeException` which call `super`. – Captain Man Apr 05 '23 at 16:45
88

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.
    ...
}
Per Lundberg
  • 3,837
  • 1
  • 36
  • 46
Markus Lausberg
  • 12,177
  • 6
  • 40
  • 66
  • 6
    Definitely proper in Java to catch specific exceptions than generic and checking for instance of. +1 – amischiefr Jul 08 '09 at 12:21
  • And lets hope FooException is unchecked or is declared in the enclosing method's throws part. C# exceptions are unchecked and can be re-thrown freely – akarnokd Jul 08 '09 at 13:19
  • 8
    -1 because you should never catch plain "Exception" unless you know what you're doing. – Stroboskop Jul 29 '09 at 09:50
  • 24
    @Stroboskop: true, but to answer it's best to use the same (similar) code as in the question! – user85421 Jul 29 '09 at 11:18
  • In this case, yes. However, sometimes, you can recover from a custom exception only if the attributes of the (custom) exception have some "recoverable" values, hence the interest of the above form. – bernard paulus Aug 20 '13 at 08:41
  • 22
    Sometimes catching all exceptions is ok. Such as when you are writing a test case. Or for logging purposes. Or in the main where not catching means crashing. – John Henckel Nov 25 '14 at 13:59
  • 2
    @JohnHenckel and others: Valid points inded. I updated the question to make it clear that catching `Exception` is typically not the right thing to do, in _most_ (but not all) cases. – Per Lundberg Jul 19 '19 at 11:41
21

In Java is almost the same:

try
{
   ...
}
catch (Exception e)
{
   if (e instanceof FooException)
     throw e;
}
alves
  • 1,343
  • 1
  • 10
  • 16
  • 36
    I would add a specific catch for FooException – dfa Jul 08 '09 at 11:49
  • 3
    In this specific case I agree, but adding a specific catch may not be the right choice - imagine you have some common code for all exceptions and after, for a particular exception, rethrow it. – alves Jul 08 '09 at 11:54
  • 1
    @MarkusLausberg But finally doesn't catch exceptions. – Robert Jul 27 '12 at 00:01
  • 2
    Yes, but this was not the question. – Markus Lausberg Jul 27 '12 at 08:21
  • As you mention in the comment, this code would only make sense if you have more code that uses `e` after the if. Otherwise, it's just not quite right to use `instanceof`. You could add an ellipsis or comment stating that. – istepaniuk Aug 18 '21 at 13:23
15

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

David M
  • 71,481
  • 13
  • 158
  • 186
7

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); }

Sindre
  • 210
  • 4
  • 8
6

something like this

try 
{
  ...
}
catch (FooException e) 
{
  throw e;
}
catch (Exception e)
{
  ...
}
cdeszaq
  • 30,869
  • 25
  • 117
  • 173
5
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.

Daniel
  • 2,380
  • 29
  • 44
3

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....:)

Matthias
  • 440
  • 3
  • 16
  • 1
    Avoid self-made extraction of info about `e`. Better pack the original exception with `throw new RuntimeException("Some usefull info", e)`. In the string, gives somes usefull info that are missing in `e`, for example some important arguments of your method, info about the context, or whatever will help debugging. – Florian H. May 05 '22 at 13:55
  • Please don't do this : 1. You are packing checked exception in RuntimeExceptions. 2. You are loosing informations – mgueydan Feb 07 '23 at 11:23