How Lombok @SneakyThrows is hacking Java!

@SneakyThrows annotation behind the scenes for Java developers

Dhib Dhafer
2 min readJan 7, 2022

If you are a Java developer and you never used Lombok (even for demo projects !) then you should quickly refer to the documentation and start using it.

Why this annotation ?

Dealing with checked exceptions could be in two ways:
- Directly catch the exception
- Or, add it the to the method signature to catch it later

Sometimes we don’t want to do what is listed above. However, we want to throw the checked exception but without declaring it in the method signature.

For example: Implementing an interface that does not allow throwing exceptions

That’s what happens when we use the @SneakyThrows annotation

@SneakyThrows can be used to sneakily throw checked exceptions without actually declaring this in your method's throws clause

How it works ?

Let’s try to create this Main class to check what is going under the hood.

class Main {


@SneakyThrows(IOException.class)
static void throwException(final String a) {
throw new IOException();
}

public static void main(String[] args) {
try {
throwException("A") ;
}catch (Exception ex){
System.out.println("Hello World!");
}
}

}

What we are doing in the reality is creating a method that throws an exception IOException, which is a checked exception, and then calling the method in the main (KISS principle).

So let’s have a look on the generated code !

class Main {
Main() {
}

static void throwException(String a) {
try {
throw new IOException();
} catch (IOException var2) {
throw var2;
}
}

public static void main(String[] args) {
try {
throwException("A");
} catch (Exception var2) {
System.out.println("Hello World!");
}

}
}

Surprise !

In the compilation phase, thanks to annotation processing, Lombok is transforming the method annotated with @SneakyThrows(IOException.class) and surrounding the method with a try catch block !

You can say: OH! this is bullshit ! I can do it myself since the beginning and catch my exception alone!

Here is the trick ! Have a close look the catch block.
It is actually re-throwing the exception caught in the try !
If you type the same generated method, the compilation would fail because it is an unhandled exception.

However, the generated code can’t be compiled again! We have bytecode that represents code that wouldn’t actually be compilable.

Conclusion

Lombok is generating code (try-catch block) that bypasses the compilation and not compilable.
Yes, @SneakyThrows fakes out the compiler.

Don’t forget to use a general catch for Exception, down the call stack, to catch the invisible checked exception.

--

--

Dhib Dhafer

Software Java developer who tries to make his code as clean as possible