JDK-8244997 : Convert the JavaThread::_threadObj oop to use OopStorage
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 15
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2020-05-14
  • Updated: 2024-11-18
  • Resolved: 2020-08-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 16
16 b11Fixed
Related Reports
Blocks :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Use of raw oops, like JavaThread::_threadObj, introduce tight coupling between the runtime and GC code, and can constrain how the GC must operate to ensure such oops are maintained correctly (i.e. by calling oops_do when needed).

The OopStorage API was introduced to allow decoupling of the runtime and the GC in this area, so we should look at converting the _threadObj to use OopStorage.

There are a couple of complexities to consider here:

1. The _threadObj oop is also accessed directly by the JIT code as an intrinsic implementation for java.lang.Thread:;currentThread(). That method has always been "hot" with regard to performance so we need to ensure performance is maintained.

2. The time that we would want to clear the _threadObj storage is after the JavaThread is no longer on any secondary ThreadsLists (just before, or as part of JavaThread destructor execution). However at that time it is not allowed for the terminating thread to interact with OopStorage. Consequently we would have to hand off to another thread (e.g. the ServiceThread) to do the release. A synchronous handoff is relatively simple but might introduce a serialization bottleneck for thread termination. An asynchronous handoff requires a queue and appropriate locking strategies that then have to interact with the Service_lock correctly. This could also have performance implications.

Note that since JDK-8240588 we handle the "clearing' of _threadObj via the exiting threads list, which is walked by Universe::oops_do at a safepoint.
Comments
URL: https://hg.openjdk.java.net/jdk/jdk/rev/0d85246cf94b User: coleenp Date: 2020-08-07 11:54:39 +0000
07-08-2020

I read that. I wanted to know why.
02-07-2020

That is exactly why this bug was filed - as per the description: 2. The time that we would want to clear the _threadObj storage is after the JavaThread is no longer on any secondary ThreadsLists (just before, or as part of JavaThread destructor execution). However at that time it is not allowed for the terminating thread to interact with OopStorage.
02-07-2020

It looks like the OopStorage::release call in ~JavaThread causes a barrier, which needs to be flushed before ~PtrQueue destructor: # assert(_buf == __null) failed: queue must be flushed before delete V [libjvm.so+0x14b39d9] PtrQueue::~PtrQueue()+0x39 V [libjvm.so+0x16c2a65] Thread::~Thread()+0x405 V [libjvm.so+0x16c30fe] JavaThread::~JavaThread()+0x27e V [libjvm.so+0x16dff4f] ThreadsSMRSupport::smr_delete(JavaThread*)+0x3f V [libjvm.so+0xdedacd] jni_DetachCurrentThread+0xad on_thread_detach flushes the SATB queue, and nothing is allowed to go in there afterward, because a following GC before the destructor won't see that queue so any entries that get added to it could become stale.
01-07-2020

Fixed typo: existing threads list -> exiting threads list
03-06-2020

Thank you!
14-05-2020