Home » Java » Core Java » A wicked Java trick to make the JVM forget to check exceptions

About Johannes Brodwall

Johannes Brodwall
Johannes is the chief scientist of the software offshore company Exilesoft. He's got close to 15 years programming Java, C# and a long time ago other languages as well. He believes that programming is about more than just writing the code, but that too many people lose touch with the coding as well. He has been organizing software development activities in Oslo for many years. In addition, he often speaks at conferences all over Europe.

A wicked Java trick to make the JVM forget to check exceptions

I’ve long time been a critic of the mechanism of compiler checked exceptions in Java. Whether you love them or hate then, one thing is sure: There’s situations where you don’t want to have to deal with them. The solution in Java is to wrap a checked exception in new RuntimeException(e) but this gives long stack traces without adding useful information. Sometimes, we just want to tell the compiler to chill.

As it turns out this is possible, through some wicked abuse of the type erasure misfeature of Java-generics. Seeing this in action is instructive for understanding the inner workings for Java. Let’s go!

Here is what we want:

  public static void main(String[] args) {
        businessLogic();
    }
 
    private static void businessLogic() {
        List<String> configuration = readConfigurationFile();
        System.out.println(configuration.get(0));
    }
 
    private static List<String> readConfigurationFile() {
        try {
            return Files.readAllLines(Paths.get("non", "existing", "file"));
        } catch (IOException e) {
            throw softenException(e);
        }
    }

Notice that the businessLogic() neither catches IOException or declares that it throws IOException. Instead, the softenException() method removes the checkedness of the exception. When we run it, we get the following stack trace:

Exception in thread "main" java.nio.file.NoSuchFileException: non\existing\file
	at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79)
	at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
	at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
	at sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:230)
	at java.nio.file.Files.newByteChannel(Files.java:361)
	at java.nio.file.Files.newByteChannel(Files.java:407)
	at java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:384)
	at java.nio.file.Files.newInputStream(Files.java:152)
	at java.nio.file.Files.newBufferedReader(Files.java:2784)
	at java.nio.file.Files.readAllLines(Files.java:3202)
	at java.nio.file.Files.readAllLines(Files.java:3242)
	at insanejava.SoftenExceptionsDemo.readConfigurationFile(SoftenExceptionsDemo.java:21)
	at insanejava.SoftenExceptionsDemo.businessLogic(SoftenExceptionsDemo.java:15)
	at insanejava.SoftenExceptionsDemo.main(SoftenExceptionsDemo.java:11)

Huh! The exception being thrown in the main method is a NoSuchFileException, which is a subclass of IOException – a checked exception! How can that be? Why didn’t any of the methods in the program have to declare throws IOException?

Here’s the trick:

  private static RuntimeException softenException(Exception e) {
        return checkednessRemover(e);
    }
 
    private static <T extends Exception> T checkednessRemover(Exception e) throws T {
        throw (T) e;
    }

The checkednessRemover method uses a trick that reveals a few things about the inner workings of Java. First, the generic type argument T is bound to RuntimeException in order to fulfill the contract of softenException. This means that the expression throws T becomes throws RuntimeException, which the compiler interprets as if there was no exceptions thrown.

But the statement throw (T)e; theoretically should evaluate to throw (RuntimeException)e;. Since e is a NoSuchFileException, you would expect this statement to result in a ClassCastException. But the way generics work in Java, the type information is removed by the compiler. So instead, the bytecode reads as throw (Exception)e;, which is fine.

So this strange trick shows that the Java compiler removes generic information from the compiled code and that checked exceptions is purely a feature of the compiler. There are no runtime verifications of checked exceptions.

Would I recommend using this trick in production code? I don’t know. It’s pretty weird and may not be that useful, but I do use it myself when I’m feeling wicked. If nothing else, I hope learning about has given you some insights into the inner workings of Java.

Disclaimers: (1) I read about this trick somewhere else, but I cannot find the source any longer. I thought it was Heinz Kabutz’ excellent Java Specialist newsletter, but I can’t find the source. (2) This is also implemented in Project Lombok as @SneakyThrows. If you are using Lombok, you should under no circumstance reimplement the trick from this blog. Use @SneakyThrows instead.

Published on Java Code Geeks with permission by Johannes Brodwall, partner at our JCG program. See the original article here: A wicked Java trick to make the JVM forget to check exceptions

Opinions expressed by Java Code Geeks contributors are their own.

(+1 rating, 1 votes)
You need to be a registered member to rate this.
Start the discussion Views Tweet it!
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
Email address:

Leave a Reply

avatar
  Subscribe  
Notify of