JDK-8210024 : JFR calls virtual is_Java_thread from ~Thread()
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jfr
  • Affected Version: 12
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2018-08-28
  • Updated: 2020-07-17
  • Resolved: 2018-11-15
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 11 JDK 12 Other
11.0.7Fixed 12 b21Fixed openjdk8u262Fixed
Related Reports
Blocks :  
Relates :  
Description
is_thread_lock_aversive calls is_Java_thread on the current thread, which is the thread being destroyed by ~Thread below. In this context, because is_Java_thread is virtual with a definition in Thread that returns false, the result will be false, even though the thread used to be a JavaThread; because ~JavaThread has run it's no longer of that type.

#3  0x0000153ba965cc5f in is_thread_lock_aversive () at ../../src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp:65
#4  JfrPostBox::post (this=0x153b240bc780, msg=<optimized out>) at ../../src/hotspot/share/jfr/recorder/service/jfrPostBox.cpp:74
#5  0x0000153ba968bfb0 in JfrThreadLocal::release (thread=0x153b4456b000, buffer=<optimized out>)
    at ../../src/hotspot/share/jfr/support/jfrThreadLocal.cpp:110
#6  JfrThreadLocal::on_destruct (thread=thread@entry=0x153b4456b000) at ../../src/hotspot/share/jfr/support/jfrThreadLocal.cpp:92
#7  0x0000153ba95fa6ee in Jfr::on_thread_destruct (thread=thread@entry=0x153b4456b000) at ../../src/hotspot/share/jfr/jfr.cpp:72
#8  0x0000153ba9eeb353 in Thread::~Thread (this=this@entry=0x153b4456b000, __in_chrg=<optimized out>)
    at ../../src/hotspot/share/runtime/thread.cpp:382
#9  0x0000153ba9eec4f1 in JavaThread::~JavaThread (this=0x153b4456b000, __in_chrg=<optimized out>)
    at ../../src/hotspot/share/runtime/thread.cpp:1705
#10 CompilerThread::~CompilerThread (this=0x153b4456b000, __in_chrg=<optimized out>) at ../../src/hotspot/share/runtime/thread.cpp:3359
#11 CompilerThread::~CompilerThread (this=0x153b4456b000, __in_chrg=<optimized out>) at ../../src/hotspot/share/runtime/thread.cpp:3367
#12 0x0000153ba9f089a5 in ThreadsSMRSupport::smr_delete (thread=thread@entry=0x153b4456b000) at ../../src/hotspot/share/runtime/threadSMR.cpp:997
#13 0x0000153ba9efd708 in JavaThread::smr_delete (this=0x153b4456b000) at ../../src/hotspot/share/runtime/thread.cpp:225
#14 JavaThread::thread_main_inner (this=this@entry=0x153b4456b000) at ../../src/hotspot/share/runtime/thread.cpp:1817
#15 0x0000153ba9efd9e9 in JavaThread::run (this=0x153b4456b000) at ../../src/hotspot/share/runtime/thread.cpp:1791


Comments
Replacing jdk8u-fix-request with link to JDK-8239140
17-02-2020

RFC: https://mail.openjdk.java.net/pipermail/jdk8u-dev/2020-January/011063.html
30-01-2020

Fix request This fix is required by https://bugs.openjdk.java.net/browse/JDK-8225797 backport to JDK 11u. The fix applies with minimal changes - the change is being reviewed in https://mail.openjdk.java.net/pipermail/jdk-updates-dev/2019-November/002115.html Tests from jdk_tier1, jdk_tier2 and jdk_core are all passing.
16-11-2019

Markus and I discussed eliminating on_thread_destruct and moving the current behavior of that function into on_thread_exit. If I find myself waiting for this to be resolved before anyone else has a chance to work on it, I will claim it and try that approach.
18-10-2018

Unfortunately I don't have the time to address this just now. Please feel free to suggest something if this is blocking you.
12-10-2018

I discovered another similar problem with Jfr::on_thread_destruct. It calls JfrThreadLocal::on_destruct, which releases the JNI handle holding the the event writer, if there is one. That release of a JNI handle involves a G1 write barrier. The G1 pre-barrier is sensitive to the thread state; a Java thread must be in the Java threads list. The current code "accidentally" works because by the time that write barrier is invoked the current thread is no longer a JavaThread, but has been demoted to merely Thread as part of destruction. Because the current thread is no longer a JavaThread, the G1 pre-barrier uses the shared SATB queue rather than the thread-local queue. This is blocking the elimination of the shared queues (JDK-8209974).
11-10-2018

Note that this problem was uncovered when I tried to make Thread::is_Java_thread pure virtual, with implementations in JavaThread and NonJavaThread.
03-09-2018

Thanks Kim. I don't think there are any problematic consequences with this situation: The main reason for this claim is that the message delivered as part of thread destruction is MSG_DEAD_BUFFER, which is categorized as an asynchronous event. The thread will attempt a try_lock() and a notify() if successful, and granted that the thread is still a Thread, this should still work (unless SMR thinks something else). Your observation do raise the point of the relevance of is_thread_lock_aversive(), which is a remnant prior to the try_lock() constructions, and I might take this bug to revisit / remove this check. Thanks again Markus
28-08-2018