ExecutorService makes exceptions disappear in a bad way

(written by lawrence krubner, however indented passages are often quotes). You can contact lawrence at: lawrence@krubner.com

I have been bitten by this many times, mostly in Clojure libraries that use ExecutorService under the hood:

What will be the result of the following snippet?

executorService.submit(() -> {
System.out.println(1 / 0);
I got bitten by that too many times: it won’t print anything. No sign of java.lang.ArithmeticException: / by zero, nothing. Thread pool just swallows this exception, as if it never happened. If it was a good’ol java.lang.Thread created from scratch, UncaughtExceptionHandler could work. But with thread pools you must be more careful. If you are submitting Runnable (without any result, like above), you must surround whole body with try-catch and at least log it. If you are submitting Callable, ensure you always dereference it using blocking get() to re-throw exception:

final Future division = executorService.submit(() -> 1 / 0);
//below will throw ExecutionException caused by ArithmeticException

Interestingly even Spring framework made this bug with @Async, see: SPR-8995 and SPR-12090.