views:

172

answers:

5

I want a method that can throw any Throwable including sub classes of Exception. Ive got something that takes an exception, stashes it in a thread local, then invokes a class.newInstance. That class ctor declares that it throws Exception then takes the threadlocal and throws it. Problem is it does not work for the two declared Exceptions thrown by Class.newInstance() namely IllegalAccessException and InstantiationException.

Im guessing any other method using some sun.* class is just a hack and not really reliable.

Wrapping is not an option because that means catchers are catching a diff type and that's just too simple and boring...

    static public void impossibleThrow(final Throwable throwable) {
    Null.not(throwable, "throwable");
    if (throwable instanceof RuntimeException) {
        throw (RuntimeException) throwable;
    }
    if (throwable instanceof Error) {
        throw (Error) throwable;
    }
    try {
        THROW.set((Exception) throwable);
        THROWER.newInstance();
    } catch (final InstantiationException screwed) {
        throw new Error(screwed);
    } catch (final IllegalAccessException screwed) {
        throw new Error(screwed);
    } finally {
        THROW.remove();
    }
}

private final static Class<Impossible> THROWER = Impossible.class;
private final static ThreadLocal<Exception> THROW = new ThreadLocal<Exception>();

static private class Impossible {

    @SuppressWarnings("unused")
    public Impossible() throws Exception {
        throw THROW.get();
    }
}
+3  A: 

If you want an Exception to bubble up through code not expecting that exception then just wrap it in a RuntimeException

} catch (RuntimeException e) {
   throw e;  // only wrap if needed
} catch (Exception e) {
   throw new RuntimeException("FOO went wrong", e);
}

Remember to let the message be informative. Some day you will have to fix a bug based only on the information in the stack trace.

Thorbjørn Ravn Andersen
+3  A: 

Wrapping an exception inside a RuntimeException (as suggested by Thorbjørn) is the way to go. However, you usually want to maintain the stacktrace of the original excpetion. Here's how:

  public static void rethrow(final Throwable t)
  {
     if(t instanceof RuntimeException)
        throw (RuntimeException) t;

     RuntimeException e = new RuntimeException(t);
     e.setStackTrace(t.getStackTrace());
     throw e;
  }
Itay
+2  A: 

From Java Puzzlers (puzzle 43):

public static void impossibleThrow(Throwable t)
{
    Thread.currentThread().stop(t); // Deprecated method.
}

The book shows other methods of achieving the same problem, one is a simplified version of yours, the other exploits generic type erasure to throw any Throwable where an Error is expected.

Dan Dyer
Will check it out sounds like a winner, wrapping is too plain and not really the same outcome.
mP
A: 

Why call:

e.setStackTrace(t.getStackTrace()); ?

You can merely unwrap it in catch statements. Generally there are much less catch statements than throw statements so this is jut less work and simpler.

Bruce
A: 

I patched javac to remove the error, compiled impossibleThrow(), renamed the source file to something that does not end in .java (which forces the next compile to use the existing .class) and used that.

Joshua