Hello,

Has it been discussed whether or not CarrierThreadLocal (currently in 
JDK.internal.misc) could/should be public API? I think it may be useful.

The introduction of virtual threads has (more or less) silently changed the 
semantics of ThreadLocal somewhat: before vthreads, ThreadLocal used to always 
be local to platform threads (because that was the only kind of thread that 
existed). With vthreads, ThreadLocal is now local to the VirtualThread, if the 
code happens to run in a vthread, or otherwise local to the PlatformThread.

I think in most cases this may be the intended behavior. Although I might point 
out that this can result in an enormous churn of ThreadLocal instances. I also 
realize that many typical use-cases are better served by the new ScopeLocal and 
that is great.

However, there are genuine use-cases where one might consciously want a 
carrier-thread-local:

We (at Datadog) have this situation: we want to associate a context (think OTEL 
span context) with (platform) threads, on the native side. And we need to 
access that context from Java. And we do so by wrapping that native context in 
a DirectByteBuffer. And because those accesses are rather frequent, we need to 
preserve the DBB and stick it in a ThreadLocal. That used to be the right thing 
to do - the native context is also thread-local after all. Now, with virtual 
threads, that ThreadLocal suddenly becomes local to the vthread. Which means 
that the DBB points to the native context of the first carrier thread that the 
vthread accessed. As soon as the vthread gets unmounted and remounted to a 
different carrier, it points to the wrong context. And even worse, when the 
original carrier thread ends, it points to any unallocated or reallocated 
memory and cause crashes and/or native heap corruptions. We have seen all of 
those symptoms.

The right thing to do is to use CarrierThreadLocal to associate the DBB with 
the correct platform thread. I realize that this might be a rather niche 
use-case, but I would think that there are more situations where storing 
information local to carrier threads might be useful.

So the question: would it be feasible to make CarrierThreadLocal a public API? 
Or is that absolutely not possible, and should we rather stick with using it 
via reflection and hope for the best?

I suppose an alternative would be to expose getCarrierThread() or similar from 
virtual threads, but that would be less elegant (at least for our use).

WDYT?

Roman

Reply via email to