JDK-6814943 : getcpool001 catches more than one JvmtiThreadState problem
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: hs14,hs15,hs19
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2009-03-09
  • Updated: 2012-02-01
  • Resolved: 2011-03-08
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 6 JDK 7 Other
6u25Fixed 7Fixed hs20Fixed
Related Reports
Relates :  
Even with the fix for 6700114 in place, the getcpool001 test continues
to fail. It fails less frequently now, but it still fails. I've verified
that the fix is in place in the HSX-14-B12 bits and in RT_Baseline after
I pushed the fix for 6700114 for HSX-15-B03. It looks like the test
catches more than one problem on almost identical code paths and I didn't
fix the second code path.

Here is my nightly analysis entry:

New nsk.jvmti failures (from 2009.03.04)
        This test failed the following assertion on Solaris SPARC
        Server VM -Xcomp (machine denab):

            Internal Error (src/share/vm/prims/jvmtiThreadState.cpp:203)
            Error: assert(_thread->get_interp_only_mode() == 1,
                "leaving interp only when mode not one")

        This failure mode is covered by the following bug:

            6700114 3/4 Assertion (_thread->get_interp_only_mode() == 1,
                        "leaving interp only when mode not one")

        This bug is in state "fix available" and the fix is included in
        the bits being tested by this nightly.


EVALUATION http://hg.openjdk.java.net/jdk7/hotspot/hotspot/rev/db2b0f8c1cef

EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-rt/hotspot/rev/db2b0f8c1cef

EVALUATION Better solution (suggested by David Holmes): Take the JvmtiThreadState_lock before accessing the JavaThread::_jvmti_thread_state field or calling JvmtiEventController::thread_ended().

EVALUATION There is a race condition in JvmtiThreadState::state_for_while_locked() and ~JavaThread(). In state_for_while_locked(), we check the terminated state of the Thread and if it is not exiting, we create the JvmtiThreadState and record it in JavaThread::_jvmti_thread_state. In ~JavaThread(), we set the _terminated field to exiting, and then check _jvmti_thread_state to see if the JvmtiThreadState object needs to be deallocated. There is no common lock code between the two, so it is possible for state_for_while_locked() to see a non-exited thread state, but then the entirety of ~JavaThread() may run in another thread before the JvmtiThreadState is created and set in the JavaThread::_jvmti_thread_state field. In that case we end up with a live JvmtiThreadState that refers to a dead thread (as the check of _jvmti_thread_state in ~JavaThread() will see NULL and not deallocate the JvmtiThreadState). A solution that appears to work: In JvmtiThreadState::state_for_while_locked(), create the state unconditionally if it does not exist, and set it in JavaThread::_jvmti_thread_state. Then check for thread exited state and if the thread has exited, "rollback" and delete the JavaThreadState. Also mark the fields _jvmti_thread_state and _terminated as volatile and use memory fences to ensure that the loads and stores of those fields are visible to other threads.