Performance Issues with Virtual Threads + ThreadLocal Caching in Third-Party Libraries (JDK 25)

Alan Bateman alan.bateman at oracle.com
Fri Jan 23 09:25:51 UTC 2026


On 23/01/2026 07:30, Jianbin Chen wrote:
> :
>
> So my question is:
>
> **In scenarios where third-party libraries heavily rely on ThreadLocal 
> for caching / buffering (and we cannot change those libraries to use 
> object pools instead), is explicitly pooling virtual threads (using a 
> ThreadPoolExecutor with virtual thread factory) considered a 
> recommended / acceptable workaround?**
>
> Or are there better / more idiomatic ways to handle this kind of 
> compatibility issue with legacy ThreadLocal-based libraries when 
> migrating to virtual threads?
>
> I have already opened a related discussion in the Dubbo project (since 
> Dubbo is one of the libraries affected in our stack):
>
> https://github.com/apache/dubbo/issues/16042
>
> Would love to hear your thoughts — especially from people who have 
> experience running large-scale virtual-thread-based services with 
> mixed third-party dependencies.
>

The guidelines that we put in JEP 444 [1] is to not pool virtual threads 
and to avoid caching costing resources in thread locals. Virtual threads 
support thread locals of course but that is not useful when some library 
is looking to share a costly resource between tasks that run on the same 
thread in a thread pool.

I don't know anything about Aerospike but working with the maintainers 
of that library to re-work its buffer management seems like the right 
course of action here. Your mail says "byte buffers". If this is 
ByteBuffer it might be that they are caching direct buffers as they are 
expensive to create (and managed by the GC). Maybe they could look at 
using MemorySegment (it's easy to get a ByteBuffer view of a memory 
segment) and allocate from an arena that better matches the lifecycle.

Hopefully others will share their experiences with migration as it is 
indeed challenging to migrate code developed for thread pools to work 
efficiently on virtual threads where there is 1-1 relationship between 
the task to execute and the thread.

-Alan

[1] https://openjdk.org/jeps/444#Thread-local-variables


More information about the loom-dev mailing list