Promptly freeing the per-thread cached direct buffers when a thread exits

Tony Printezis tprintezis at
Fri Apr 6 13:46:33 UTC 2018

Hi David,

ThreadLocals getting cleared is not enough. The threadLocals field is
cleared by Thread::exit:

    private void exit() {
        threadLocals = null;

but this doesn’t really do anything. The GC has to run, find the direct
buffer in the ThreadLocal unreachable, and queue its Cleaner for
processing. I’m looking for a hook to explicitly reclaim the direct buffer
when Thread::exit is called.


Tony Printezis | @TonyPrintezis | tprintezis at

On April 5, 2018 at 6:07:26 PM, David Holmes (david.holmes at

Hi Tony,

On 6/04/2018 7:45 AM, Tony Printezis wrote:
> Hi all,
> We recently hit another interesting issue with the NIO thread-local
> DirectByteBuffer cache. One of our services seems to create and drop

If it's in a ThreadLocal then aren't you just asking for thread-locals
to be cleared at thread exit?


> threads at regular intervals. I assume this is due to a thread pool
> dynamically resizing itself.
> Let's say a thread starts, lives long enough for its Thread object to be
> promoted to the old gen (along with its cached direct buffer), then
> This will result in its cached direct buffer(s) being unreachable in the
> old gen and will only be reclaimed after the next full GC / concurrent GC
> cycle.
> Interestingly, the service in question does concurrent GC cycles really
> infrequently (one every few days) as it has a really low promotion rate.
> This results in the JVM's total direct size constantly increasing (which
> effectively a native buffer leak).
> Has anyone come across this issue before?
> There are a few obvious ways to mitigate this, e.g., cause a Full GC /
> concurrent GC cycle at regular intervals. However, the best solution IMHO
> is to explicitly free any direct buffers that are still in the cache when
> thread exits.
> I'll be happy to implement this and test it internally at Twitter, if
> not on anyone else's radar. However, to do what I'm proposing I need some
> sort of thread exit hook. Unfortunately, there doesn't seem to be one.
> Would proposing to introduce thread exit hooks be reasonable? Or is
> everyone going to freak out? :-) The hooks can be either per-Thread or
> per-ThreadLocal. And it's OK if the hooks can only be used within
> FWIW, I did a simple prototype of this (I call the hooks from
> and it seems to work as expected.
> Any thoughts / feedback on this will be very appreciated.
> Thanks,
> Tony
> —————
> Tony Printezis | @TonyPrintezis | tprintezis at

More information about the core-libs-dev mailing list