Help! My Clojure Exception Has an Empty Stacktrace!

This is a blog about the development of Yeller, The Exception Tracker with Answers

Read more about Yeller here

Ever seen a Java exception with an empty stacktrace? Even in development?

Something that looks like this:

java.lang.NullPointerException

No stacktrace at all.

Folk get bit pretty hard by this.

That sucks. How are you meant to debug something when there’s no stacktrace? Why the shit is there no stacktrace?

It turns out that there’s a particular JVM optimization (which is on by default) that causes this to happen. It’s a pretty important optimization - it can vastly speed up exceptions that are used for control flow (which happens in some libraries, and the JVM wants to optimize for it). However, it really screws up debugging.

For performance purposes, when such an exception is thrown a few times, the method may be recompiled. After recompilation, the compiler may choose a faster tactic using preallocated exceptions that do not provide a stack trace. To disable completely the use of preallocated exceptions, use this flag: -XX:-OmitStackTraceInFastThrow.

If you want to read more about the performance implications, this excellent JMH post, and this post from one of the Netty authors both cover it in detail.

Thankfully, turning it off is very simple, just pass this extra command line flag to java:

-XX:-OmitStackTraceInFastThrow

If you’re using Clojure with Leiningen, you don’t have to do anything in development - this optimization is off by default. But if you’re just invoking an uberjar in production via java -jar, you’ll need to turn it on (of course, you might not want to because of the perf implications).

This is a blog about the development of Yeller, the Exception Tracker with Answers.

Read more about Yeller here

Looking for more about running production applications, debugging, Clojure development and distributed systems? Subscribe to our newsletter: