Luigi is a passionate software developer working in Java since 2000. In 2001 he co-founded the Java User Group Torino, the first local JUG in Italy. Quickly after that, many other JUGs have born in Italy following JUG Torino's example. Since some years now, he is working as free lance software consultant between Italy, Germany, UK and Switzerland, on several industries. His personal interests include software, science fiction books and movies, traveling, photography and good food. Luigi is a DZone MVB and is not an employee of DZone and has posted 19 posts at DZone. You can read more from them at their website. View Full User Profile

Throwing Undeclared Checked Exceptions

09.15.2010
| 8059 views |
  • submit to reddit

Sometimes checked exceptions can be a problem. For instance, recently I tried to implement some common logic to retry failing network operations and it resulted in a kind of command pattern on which, as usual, the execute() method throws java.lang.Exception. That complicated the caller code which has to catch and handle java.lang.Exception instead of the more specific exceptions...

I knew that checked exceptions are enforced by the compiler, while in the virtual machine there is nothing preventing a checked exception to be thrown by a method not declaring it, so I started to check on internet how to implement this.
I found two posts on Anders Noras's blog (#1 #2) on how to perform this magic.

Method #1: the sun.misc.Unsafe class

import java.lang.reflect.Field;
import sun.misc.Unsafe;

public class UnsafeSample {
    public void methodWithNoDeclaredExceptions( ) {
        Unsafe unsafe = getUnsafe();
        unsafe.throwException( new Exception( "this should be checked" ) );
    }

    private Unsafe getUnsafe() {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            return (Unsafe) field.get(null);
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main( String[] args ) {
        new UnsafeSample().methodWithNoDeclaredExceptions();
    }
}

This makes use of internal Sun JRE libraries implementation classes. It could not work if you use a non Sun VM. And in fact it doesn't if you use GCJ (The GNU compiler for Java).
The getUnsafe() method exposed above does some tricks to access a private field in the Unsafe class, because Unsafe.getUnsafe() can only be called by classes loaded by the bootstrap ClassLoader.

See also the article Avoiding Checked Exceptions by Don Schwarz.

Method #2: the Thread.stop(Exception)

public class ThreadStopExample {

    @SuppressWarnings("deprecation")
    public void methodWithNoDeclaredExceptions( ) {
        Thread.currentThread().stop(new Exception( "this should be checked" ));
    }

    public static void main( String[] args ) {
        new ThreadStopExample().methodWithNoDeclaredExceptions();
    }
}

This uses a deprecated method, but works. No portability issue, until the Java specification guys decide to remove the method.
It could have some side effects on the current thread as we are calling stop(). I'm not sure.

Method #3: using Class.newInstance()

Look at the signature of java.lang.Class.newInstance() and compare it to Constructor.newInstance()

public final class Class  ... {
    public T newInstance()
        throws InstantiationException, IllegalAccessException
}

public final class Constructor ... {
    public T newInstance(Object ... initargs)
    throws InstantiationException, IllegalAccessException,
               IllegalArgumentException, InvocationTargetException
}

You see it? no InvocationTargetException!
If you call SomeObject.class.newInstance() and the constructor throws an exception, the exception doesn't get wrapped into the InvocationTargetException (that is a checked exception).
So you can write an utility class like this, to throw checked exceptions without needing to declare them on the method signature.

public class Exceptions {
    private static Throwable throwable;

    private Exceptions() throws Throwable {
        throw throwable;
    }

    public static synchronized void spit(Throwable throwable) {
        Exceptions.throwable = throwable;
        try {
            Exceptions.class.newInstance();
        } catch(InstantiationException e) {
        } catch(IllegalAccessException e) {
        } finally {
            Exceptions.throwable = null;
        }
    }
}

public class TestExceptionSpit {
    public static void main(String[] args) {
        Exceptions.spit(new Exception( "this should be checked" ));
    }
}

Internally the Class.newInstance() uses the sun.misc.Unsafe class, but in this case this technique is fully portable because you are not using any deprecated or internal method. In fact it works also with GCJ JVM.
I tried to remove the synchronization stuff and the static field using an inner class, but it seems that the compiler does some strange trick translating the empty constructor in something else preventing Class.newInstace() to be used on that inner class.

The behavior of the Class.newInstance() is also documented:

"Note that this method propagates any exception thrown by the nullary
constructor, including a checked exception. Use of this method
effectively bypasses the compile-time exception checking that would
otherwise be performed by the compiler."

So your code is fully safe and compliant to the rules :)

Method #4: the sun.corba.Bridge

import java.rmi.RemoteException;

public class Bridge {
    public void methodWithNoDeclaredExceptions( ) {
        sun.corba.Bridge.get().throwException(new RemoteException("bang!"));
    }

    public static void main( String[] args ) {
        new Bridge().methodWithNoDeclaredExceptions();
    }
}

This is more or less the same as using the Unsafe.class. The difference is that in this case you don't need to do the reflection stuff to access the private field "theUnsafe", because the Bridge class is doing that for you. Still using an internal JRE class with same portability issues.

Method #5: Generics

The following example takes advantage of the fact that the compiler does not type check generics...

import java.rmi.RemoteException;

class Thrower {
    public static void spit(final Throwable exception) {
        class EvilThrower<T extends Throwable> {
            @SuppressWarnings("unchecked")
            private void sneakyThrow(Throwable exception) throws T {
                throw (T) exception;
            }
        }
        new EvilThrower().sneakyThrow(exception);
    }
}

public class ThrowerSample {
    public static void main( String[] args ) {
        Thrower.spit(new RemoteException("go unchecked!"));
    }
}

Credits to "Harald" that posted a comment on Johannes Brodwall's blog.
I personally think this last one is the best solution: it uses a feature of the compiler against itself.

Conclusions

I think that having checked exception in Java is better than not having it. I already expressed why I am in favor of checked exceptions here. It's a design decision, you can choose to make your exceptions checked or unchecked, if you want to force your client to handle them or not; you can't do that on .NET, where checked exceptions simply do not exist.

Sometimes you have (or you have to write) methods throwing java.lang.Exception, and you get into the trap. So you may like to know that there is a dirty escape, and you can decide to use it or not... we saw that Sun is throwing undeclared checked exceptions in Class.newInstace(), ask yourself: if this is good for the JRE code, could it be good also for yours?

Usually you can wrap checked exception into RuntimeExceptions but this doesn't simplify the client code, because the caller in case of needing has to catch the RuntimeException, unwrap the cause and deal with it. Maybe a new Java keyword to throw checked exception without requiring the caller to handle them could help: I recommend reading post on Ricky Clarkson's about checked exceptions.

Finally I come to the decision to not use those tricks in my object doing the retry logic, and keep the messy catch logic on the caller code. In case of needing I will evaluate to use a Dynamic Proxy doing the retry logic and keeping its behavior transparent to the client.

To those who wants unchecked exceptions in Java... well, there is the way to have it: the example with Generics is a clean way to have it. Use it if you want, at your own risk.
Personally I would choose to use libraries with checked exceptions...

Other related articles

Friday Free Stuff by Chris Nokleberg, uses bytecode manipulation.
Don't Try This at Home by Bob Lee, exposes some methods also covered above.

 

From: http://en.newinstance.it/2008/11/17/throwing-undeclared-checked-exceptions/

Published at DZone with permission of Luigi Viggiano, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Alessandro Santini replied on Wed, 2010/09/15 - 2:38am

I personally would have come to a slightly (but just slightly) different conclusion: I would have kept the exception catch/retry logic in the command bean. This way, you could implement different Commands aiming at the same Target but with different logic (with or without retry, for instance). Being a Command, all these implementations would be sharing the same interface.

Why the execute() method must  necessarily return Exception? The Command bean could again be an excellent substitute for exception conversion (from the target context to the client context) e.g. converting an SoapException into something more like InvalidCommandException.

If I did not understand the context of your problem, my apologies :)

Ciao,

Alessandro

Fabrizio Giudici replied on Wed, 2010/09/15 - 3:33am

Another way is to use the @SneakyThrows thing from project Lombok.

Luigi Viggiano replied on Wed, 2010/09/15 - 8:59am

Fabrizio (ciao!)

I knew Lombok, but I didn't knew this feature... The problem with those exception is that the compiler will refuse to catch those exception because "exception XyzCheckedException is never thrown in body of corresponding try statement"

It's important to not abuse those techniques then... actually it's very hard to do a good usage of it :-)

I am not recommending to use those, but still it's good to know about it.

Luigi Viggiano replied on Wed, 2010/09/15 - 9:33am in response to: Alessandro Santini

Alessandro,

I didn't explain in detail how my little Retry logic had to work. Basically it was something like:

retry(times(3), delay(5000, ms), new Logic() {
    public void run() throws Throwable {
        ...
    }
})
.when(RemoteException.class, new RemoteExceptionHandler())
.when(SocketException.class, retry())
.when(FooBarException.class, ignore())
.when(NoRouteToHostException.class, abort())
.execute();

the execute() method shall still throw one of the exception that caused the retry or the abort, so the application can still receive the signal of what went wrong and why. I mean: I retry three times when there is a SocketException but the 4th time I let the exception to flow out. For this reason, the execute() method, that has to be independen from the internal logic, must still throw out any possible exception that the Logic object may throw. I don't know if I clarified. 

At the end I had to put the above code in a try catch.

BTW, I didn't go in detail of the scope of the retry logic above, as it is, in my opinion, less interesting than how the compiler can be cheated to do something "impossible" :-)

Fabrizio Giudici replied on Wed, 2010/09/15 - 1:04pm in response to: Luigi Viggiano

Hey, pretty cool stuff Luigi! I've seldom implemented retry logic so far, but your code example makes me wanting to do that! :-)

Alessandro Santini replied on Wed, 2010/09/15 - 3:01pm in response to: Fabrizio Giudici

Indeed - I love internal DSLs a lot :)

Liam Knox replied on Wed, 2010/09/15 - 9:29pm

Are you sure the Generic example applies still? Looking at Java 6, atleast with Eclipse, this gets flagged as a compile error

Luigi Viggiano replied on Wed, 2010/09/15 - 10:13pm in response to: Liam Knox

Liam, which example gives you errors?

Liam Knox replied on Wed, 2010/09/15 - 10:45pm in response to: Luigi Viggiano

I see that the Generics implementation get caught by the compiler in Java 5/6

<code>

C:\tmp>javac -cp . thrower/Thrower.java

thrower\Thrower.java:11: unreported exception java.lang.Throwable; must be caugh t or declared to be thrown new EvilThrower().sneakyThrow(exception); ^ 1 error

</code>

Liam Knox replied on Thu, 2010/09/16 - 3:09am in response to: Luigi Viggiano

You could actually do something quite fluid using Proxies. i.e. along the ways Mockito builds up its mock objects.
R r = retry(new R(), retryAdvice).someMethod();
r.someMethod(); // will now retry based on the advice implicitly
In this way you can decorate any existing object(final caveats etc) behaviour as Retryable with out needing the SAM type. Horses for courses really

We actually used a full annotation based AOP approach in certain areas

Bozhidar Bozhanov replied on Fri, 2010/09/17 - 1:51am

And what is the problem of

throw new RuntimeException(originalException);

Liam Knox replied on Fri, 2010/09/17 - 10:43pm in response to: Bozhidar Bozhanov

I think the problem with this in general is contractually, if you decorate behaviour of a function you still want the original contract maintained. In this way any original error handling in the caller is retained. By wrapping exceptions this is violated

My 2 cents. Checked exception are a complete pile of crap, the whole heirachy is a mess, there use cases in the core APIs are wrong ( see IOException, FormatException, SQLException etc ) and in the end for what tangilble gain? None.

Designers miss the point totally, having 2 variants of an idiom does not increase the complexity by a factor of 2. It increases it anywhere between 2 an infinity. In the world of exceptions it is more like the latter.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.