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

About Johannes Brodwall

Johannes Brodwall
Johannes works as a programmer, software architect and provocateur for Sopra Steria Norway. He loves writing code in Java, C# and JavaScript and making people think.

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 ....
I agree to the Terms and Privacy Policy

Leave a Reply

avatar

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
Notify of