Sheer Evil: Rethrowing exceptions in Java

This morning, I was looking through some code and I was annoyed (yet again) at Java’s exception hierarchy, particularly when it comes to checked exceptions. Just as a reminder, everything that can be thrown in Java derives from Throwable. The predefined direct subclasses are Error and Exception. (You can derive from Throwable directly yourself, but I’ve never seen anyone do it, thank goodness.) Exception, and any class deriving from it, count as a checked exception – one that you have to declare if your method might throw it. Oh, except for RuntimeException, and its descendants such as NullPointerException. Blech.

This is really painful in some situations. In particular, the code I was looking at wanted to catch everything, act on it, and then rethrow it. My method was declared to throw IOException, and without the catch block everything compiled fine, so I knew that nothing I was calling should throw any checked exceptions other than IOException. However, rethrowing the exception is tricky – because the compiler doesn’t know what you’re up to. I ended up with this foul code:

try
{
    // Stuff here
}
catch (Throwable t)
{
    // Log the error (or whatever)
            
    // Now rethrow
    if (t instanceof IOException)
    {
        throw (IOException) t;
    }
    if (t instanceof RuntimeException)
    {
        throw (RuntimeException) t;
    }
    if (t instanceof Error)
    {
        throw (Error) t;
    }
    // Very unlikely to happen
    throw new RuntimeException(t);
}
finally
{
    // More stuff here
}

Nasty, isn’t it? It would be lovely to somehow tell the compiler that you know there won’t be any other kinds of checked exceptions thrown, just rethrow the original, it’s all right guv, you can trust me, honest.

Well, apparently you can’t really trust me. Not since the hack I worked out this morning. You see, exception checking only occurs at compile time. So, let’s define a really harmless little class called ExceptionHelper:

public class ExceptionHelper
{
    /** Private constructor to prevent instantiation */
    private ExceptionHelper()
    {
    }
    
    public static void rethrow (Throwable t)
    {
    }
}

Nothing nasty going on, is there? So the compiler won’t mind at all if I change the original code to:

try
{
    // Stuff here
}
catch (Throwable t)
{
    // Log the error (or whatever)
            
    // Now rethrow
    ExceptionHelper.rethrow(t);
}
finally
{
    // More stuff here
}

The only trouble is, it doesn’t rethrow the exception any more, regardless of the name of the method. But as I suspect you’ve guessed by now, once we’ve satisfied the compiler, we can change ExceptionHelper.rethrow slightly:

public static void rethrow (Throwable t) throws Throwable
{
    throw t;
}

Recompile ExceptionHelper but not the calling code and we achieve exactly what we want – it will rethrow whatever exception we ask it to, and we’ve fooled the compiler into not worrying about the potential consequences. Of course, this means we could change the code in the try block to something which throws a completely different checked exception, and we’d never know until it happened – the compiler couldn’t help us. The workaround for this is to temporarily remove the catch block and see whether or not the compiler complains.

I’m not actually suggesting anyone should do this, despite a certain appeal in terms of simpler, more readable code in the catch block. A hack like this is horrible, evil, awful. Which is why I had to share it, of course.

14 thoughts on “Sheer Evil: Rethrowing exceptions in Java”

  1. Hi Jon,

    Unless I’m going senile, none of the casts in the original snippet do anything. So the example doesn’t make any sense to me.

    Like

  2. The casts are required to allow the exceptions to be thrown. IOException is allowed to be thrown because the method declared that it threw exception; RuntimeException and Error can be thrown because they’re not checked.

    If you just try to throw “t” itself, however, the compiler would complain that you hadn’t declared the method to throw “Throwable”.

    Like

  3. What are you trying to do? Your example seems to be identical to:

    public void sample() throws IOException {
    // Stuff here
    }

    It looks like //Stuff here only throws IOException, and you’re only interested in throwing IOException yourself.

    Like

  4. Please don’t ever do this. And if you do, don’t make me debug it!

    Although it’s wordier, I think the following is the right way to do it. After all, everything in Java is wordy when done right.

    try {
    callSomething();
    } catch (IOException e) {
    doStuffTo(e);
    throw e;
    } catch (Error e) {
    doStuffTo(e);
    throw e;
    } catch (RuntimeException e) {
    doStuffTo(e);
    throw e;
    } finally {
    doMoreStuff();
    }

    Like

  5. Squirrel Sewer> “// Stuff” only *declares* that it will throw IOException, but it may throw any unchecked exception too. I still want to do some logging (or whatever) on unchecked exceptions, but then rethrow the original exception.

    Carey> Oh I certainly wouldn’t use it in production code. It’s just an awful idea which appealed to me :) Your solution works, but will get messier and messier if there are multiple checked exceptions to deal with. (It also gets slightly messier if the code needs to deal with other variables, particularly if it needs to modify local variables. That’s unlikely though.) I object to repeating myself, that’s the problem…

    Like

  6. I think what has caused a bit of confusion is that Jon didn’t give the method signature in the original example.

    It probably should have been something like:

    public void myMethod() throws IOException
    {
    // Jon’s example here…
    }

    Thus just catching Throwable and re-throwing won’t compile without the casts.

    Like

  7. Yup, having the whole method would probably have helped. I did state beforehand that it was declared to throw IOException, but that’s not as clear as actually including it. Oops.

    When I get home I’ll fix the blog entry so your comment looks silly. And remove this comment, of course. (Just kidding…)

    Like

  8. The whole article looks confusing to me; you could have done better by providing full code listings and sample output.

    Like

  9. Bill: It’s often a case of getting a blog entry done quickly or not getting it done at all.

    Note that there’s no real output to the sample beyond it being able to compile.

    If I get time at some point I’ll come back and expand the examples a bit.

    Jon

    Like

  10. I agree with Laurence. Your example does not make sense. Carey has shown the correct method of handling Exceptions.

    Your method throws IOException, so dont wrap *other* exceptions to throw them as IOExceptions (“throw new RuntimeException(t);”), if you need to throw multiple exception types add them to the method signature, so the person catching them knows exactly what to expect.

    Like

  11. Mat> I don’t wrap other exceptions to throw them as IOExceptions. In the longhand version, I only do any wrapping if it’s a non-Error, non-Exception throwable.

    The point of the evil class is to avoid having to do all that code in the first place.

    Carey’s code certainly makes sense in some cases, but if the stuff that you need to do with the exception alters multiple variables, it’s not always easy to extract the logic into an extra method – and having an extra method just because of Java’s exception handling mechanism is ugly. It also doesn’t handle the case where the non-Error, non-Exception is thrown. Very rare, admittedly, but it’s handled by my code but not by Carey’s.

    Jon

    Like

  12. I have a .class file that is the equivalent of this:

    public abstract class Throwable {
    public shared sub Throw(Throwable t) {
    throw t;
    }
    }

    Note that this code does not compile, and furthermore there is no java code that can be compiled to produce the .class file I have.

    Evil, huh?

    Like

  13. You may want to look into AOP to avoid this mess. The leading Java implementation thereof is AspectJ, but it’s fairly intrusive. There are lighter-weight AOP libraries available that may suit your needs.

    If you’re unfamiliar with the concept, the wikipedia entry for Aspect-oriented_programming is a good place to start, it contains a good introduction and dozens of hyperlinks.

    Like

Leave a comment