I am the founder and CEO of Data Geekery GmbH, located in Zurich, Switzerland. With our company, we have been selling database products and services around Java and SQL since 2013. Ever since my Master's studies at EPFL in 2006, I have been fascinated by the interaction of Java and SQL. Most of this experience I have obtained in the Swiss E-Banking field through various variants (JDBC, Hibernate, mostly with Oracle). I am happy to share this knowledge at various conferences, JUGs, in-house presentations and on our blog. Lukas is a DZone MVB and is not an employee of DZone and has posted 234 posts at DZone. You can read more from them at their website. View Full User Profile

Throw Checked Exceptions Like Runtime Exceptions in Java

09.20.2012
| 9268 views |
  • submit to reddit

How to throw a checked exception without catch block or throws clause in Java? Simple!

public class Test {

    // No throws clause here
    public static void main(String[] args) {
        doThrow(new SQLException());
    }

    static void doThrow(Exception e) {
        Test.<RuntimeException> doThrow0(e);
    }

    @SuppressWarnings("unchecked")
    static <E extends Exception> void doThrow0(Exception e) throws E {
        throw (E) e;
    }
}

Due to generic type erasure, the compiler will compile something here that really shouldn’t compile. Crazy? Yes. Scary? Definitely!

The generated bytecode for doThrow() and doThrow0() can be seen here:

  // Method descriptor #22 (Ljava/lang/Exception;)V
  // Stack: 1, Locals: 1
  static void doThrow(java.lang.Exception e);
    0  aload_0 [e]
    1  invokestatic Test.doThrow0(java.lang.Exception) : void [25]
    4  return
      Line numbers:
        [pc: 0, line: 11]
        [pc: 4, line: 12]
      Local variable table:
        [pc: 0, pc: 5] local: e index: 0 type: java.lang.Exception

  // Method descriptor #22 (Ljava/lang/Exception;)V
  // Signature: <E:Ljava/lang/Exception;>(Ljava/lang/Exception;)V^TE;
  // Stack: 1, Locals: 1
  static void doThrow0(java.lang.Exception e) throws java.lang.Exception;
    0  aload_0 [e]
    1  athrow
      Line numbers:
        [pc: 0, line: 16]
      Local variable table:
        [pc: 0, pc: 2] local: e index: 0 type: java.lang.Exception

As can be seen, the JVM doesn't seem to have a problem with the checked exception thrown from doThrow0(). In other words, checked and unchecked exceptions are mere syntactic sugar

Published at DZone with permission of Lukas Eder, author and DZone MVB. (source)

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

Comments

Sinuhé Pop replied on Fri, 2012/09/21 - 8:25am

Cute! This is similar to @SneakyThrows annotation in Project Lombok.

Vitalii Tymchyshyn replied on Sun, 2012/09/23 - 2:18am

Generics are simply syntaxis sugar. You should get ClassCastException in runtime, much like here:

import java.io.IOException;
 
public class test {
    public static void main(String... args) {
try {
throw new IOException();
} catch (IOException e) {
Object o = e;
throw (RuntimeException)o;
}
}
}

 

Vitalii Tymchyshyn replied on Sun, 2012/09/23 - 2:23am in response to: Vitalii Tymchyshyn

Just tries your code. It works. It seems that there is a bug in javac as it misses the cast.  But I'd not rely on it as it can be fixed at any time.

Sandeep Kadyan replied on Sun, 2012/09/23 - 7:05am in response to: Vitalii Tymchyshyn

this works on jdk1.7.0

Orlin Gueorguiev replied on Mon, 2012/09/24 - 8:35am in response to: Vitalii Tymchyshyn

Hi Vitalii, this is not a bug. Generics work only during compile time and any generics information is discarded during runtime. This is the reason why you do not get any Class Cast Exception. You might want to read the SCJP book, where it is explained in details, that generics are treated only during compile time in order to have compatibility with previous Java version (1.4 or less).

Lukas Eder replied on Tue, 2012/09/25 - 2:46am in response to: Vitalii Tymchyshyn

See the updated post showing some bytecode. Checked exceptions are a Java-the-language feature, not a Java-the-platform feature. In other words, just syntactic sugar (or un-sugar, in this case)

Vitalii Tymchyshyn replied on Tue, 2012/09/25 - 3:23am in response to: Lukas Eder

Agree, but sugar or unsugar must be consistent. So this looks like a bug in javac that should be fixed. Consider this:
try{
   someCall()
} catch (RuntimeException e) {
   handle();
}
And now someCall starts to throw, say, IOException. This won't be catched and handled.

Lukas Eder replied on Tue, 2012/09/25 - 3:36am in response to: Vitalii Tymchyshyn

So? I doubt that it's a bug. Throwing checked exceptions had always been possible in Java. For instance using sun.misc.Unsafe.throwException(Throwable).

Some examples can be seen here:
http://stackoverflow.com/q/4375828/521799

Vitalii Tymchyshyn replied on Tue, 2012/09/25 - 4:09am in response to: Lukas Eder

JLS 11.2: For each checked exception which is a possible result, the throws clause for the method (§8.4.6) or constructor (§8.8.5) must mention the class of that exception or one of the superclasses of the class of that exception (§11.2.3).

Anything that works against JLS is either bug or hack. As for me, to qualify for a hack, scenario should be either noted as unsafe (e.g. accessing private members with reflection) or be vendor extension (like sun.misc.Unsafe). The method shown here is not a hack. This means it's a bug because it violates JLS.

Lukas Eder replied on Tue, 2012/09/25 - 5:04am in response to: Vitalii Tymchyshyn

But it isn't really a checked exception. By the fact that doThrow0()'s <E extends Exception> is bound to RuntimeException, no throws clause is necessary in doThrow().

The fact that RuntimeException is assignment-compatible to Exception means that there is no cast necessary.

I'm not sure if this is a bug in the compiler. Probably a lack of specification in the JLS, though, handling this corner-case...

I find this quite intriguing. Feel free to argue for your case on the Stack Overflow question that I've created just now:

http://stackoverflow.com/q/12580598/521799

Vitalii Tymchyshyn replied on Tue, 2012/09/25 - 5:42am in response to: Lukas Eder

JLS clearly says about "possible result". doThrow can possibly throw Exception, so it must be in it's throws clause. Or, if invalid casting is involved, ClassCastException must be thrown.

Mason Mann replied on Wed, 2013/08/07 - 9:12am in response to: Vitalii Tymchyshyn

Lukas is right, you are wrong. Get on with your life.

Comment viewing options

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