In this post I’ll describe an important patch that you always want to use
when using a ThreadPoolExecutor (or any ExecutorService) in Java.
The patch intends to mitigate the unexpected death of threads, and the impact
that they should be allowed to have on your application.
The help illustrate illustrate this, here is an example project with a very
nasty thread eating memory in it:
Compile and run this application with -Xmx16m.
You should see something like the following:
The application is stuck, we are no longer seeing any main: OK messages.
No stack traces, nothing.
The reason is that out coordinator thread allocates memory for its message,
this means that it could, and is the target of an OutOfMemoryError when the
allocation fails because BadThread has locked up all available memory and is
refusing to die.
This is when it gets interesting. ThreadPoolExecutor will happily catch and
swallow any exception being thrown in one of its tasks. As per the
documentation, it is explicitly left to the developer to handle this.
This leaves us with a coordinator at the end of the Queue to die, and main
is left to its own devices forever. :(.
This patch overrides the afterExecute
method. A hook designed to allow for custom behavior after the completion of
Run the project again, and you should see the following:
I want to emphasise that OutOfMemoryError is generally not an error that you
can safely recover from. There are no guarantees that the thread responsible
for eating up your memory is the target for this error. Even if that is the
case, this thread might become important at a later stage in its life.
In my opinion, the most reasonable thing to do is to give up.
An Error is a subclass of Throwable that indicates serious problems that a
reasonable application should not try to catch. Most such errors are abnormal
At this stage you might be tempted to attempt a clean shutdown of your
application on errors.
This might work. But we might also be in a state where a thread critical
towards the clean shutdown of your application is no longer alive.
There might not be any memory left to support a complex shutdown. Attempting it
could lead to your cleanup attempt crashing leading us back to where we