JDK-8036823 : Stack trace sometimes shows 'locked' instead of 'waiting to lock'
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 8
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_7
  • CPU: x86
  • Submitted: 2014-03-06
  • Updated: 2021-11-09
  • Resolved: 2014-05-30
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 7 JDK 8 JDK 9
7u80Fixed 8u20Fixed 9 b19Fixed
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b129)
Java HotSpot(TM) Client VM (build 25.0-b69, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

EXTRA RELEVANT SYSTEM CONFIGURATION :
Problem observed on linux-i586 and linux-x64 as well

A DESCRIPTION OF THE PROBLEM :
When stack trace information including a contended lock is obtained with Ctrl-Break, the stack trace often erroneously shows that multiple threads have locked the same object, leading to confusion and misunderstanding.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile and run the attached program
2. Obtain a stack trace multiple times (Ctrl-Break, jstack, ...)
3. Observe the results

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Threads Thread-0 and Thread-1 should never have identical lines '- locked <0xsomething> (a Test$1)' in their stack traces. One thread only should show as locking the object, while the other one should be 'waiting to lock' the same object, or just elsewhere in the code.
ACTUAL -
A thread that is shows 'waiting for monitor entry' in its stack trace header sometimes shows 'locked' on the object it is supposedly waiting to lock. See Thread-0 in the attached stack trace

ERROR MESSAGES/STACK TRACES THAT OCCUR :
2014-03-06 14:11:29
Full thread dump Java HotSpot(TM) Client VM (25.0-b69 mixed mode):

"DestroyJavaVM" #10 prio=5 os_prio=0 tid=0x0221c800 nid=0x9fac waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" #9 prio=5 os_prio=0 tid=0x14d0b800 nid=0x1474 runnable [0x1554f000]
   java.lang.Thread.State: RUNNABLE
        at Test$1.run(Test.java:6)
        - locked <0x048725f8> (a Test$1)
        at java.lang.Thread.run(Thread.java:744)

"Thread-0" #8 prio=5 os_prio=0 tid=0x14d09000 nid=0x2f4c waiting for monitor entry [0x1503f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at Test$1.run(Test.java:6)
        - locked <0x048725f8> (a Test$1)
        at java.lang.Thread.run(Thread.java:744)

"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x14cb3400 nid=0x11f4 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x14cbd400 nid=0xa188 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x14cbc400 nid=0xa160 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x14cb9400 nid=0xb780 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x14c75800 nid=0x3104 in Object.wait() [0x14eef000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x048056d8> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:142)
        - locked <0x048056d8> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:158)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x14c6f800 nid=0x2714 in Object.wait() [0x1508f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x04805200> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:157)
        - locked <0x04805200> (a java.lang.ref.Reference$Lock)

"VM Thread" os_prio=2 tid=0x14c6b400 nid=0xa180 runnable

"VM Periodic Task Thread" os_prio=2 tid=0x14cb5000 nid=0xbab4 waiting on condition

JNI global references: 13

Heap
 def new generation   total 4928K, used 718K [0x04800000, 0x04d50000, 0x09d50000)
  eden space 4416K,  16% used [0x04800000, 0x048b39c8, 0x04c50000)
  from space 512K,   0% used [0x04c50000, 0x04c50000, 0x04cd0000)
  to   space 512K,   0% used [0x04cd0000, 0x04cd0000, 0x04d50000)
 tenured generation   total 10944K, used 0K [0x09d50000, 0x0a800000, 0x14800000)
   the space 10944K,   0% used [0x09d50000, 0x09d50000, 0x09d50200, 0x0a800000)
 Metaspace       used 1553K, capacity 2242K, committed 2368K, reserved 4480K

REPRODUCIBILITY :
This bug can be reproduced often.

---------- BEGIN SOURCE ----------
public class Test {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            public void run() {
                for (;;) {
                    synchronized (this) { }
                }
            }
        };
        new Thread(runnable).start();
        new Thread(runnable).start();
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
- Take multiple stack traces if possible
- Understand that diagnostic information sometimes lies


Comments
URL: http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/b576b115df4d User: lana Date: 2014-06-18 17:19:22 +0000
18-06-2014

URL: http://hg.openjdk.java.net/jdk9/hs-rt/hotspot/rev/b576b115df4d User: dcubed Date: 2014-05-30 15:30:15 +0000
30-05-2014

Just to stress the test, I ran it on mt-haku with these changes: $ diff test/runtime/Thread/TestThreadDumpMonitorContention.java{.save.00,} 31c31 < * @run main/othervm TestThreadDumpMonitorContention --- > * @run main/othervm/timeout=2700 TestThreadDumpMonitorContention 3600 So 3600 samples and a timeout of 45 minutes. I was really close in my guess work: $ egrep 'start=|end=' JTwork/runtime/Thread/TestThreadDumpMonitorContention.jtr end=Thu May 29 09\:18\:27 MDT 2014 start=Thu May 29 08\:36\:13 MDT 2014 The test ran for ~42 minutes without a failure: $ egrep 'Sample|^Test' JTwork/runtime/Thread/TestThreadDumpMonitorContention.jtr | tail -5 Sample #3596 Sample #3597 Sample #3598 Sample #3599 Test PASSED.
29-05-2014

And my reply... On 5/29/14 9:31 AM, Daniel D. Daugherty wrote: > Robert, > > I'm finally getting back to this thread. Sorry for the delay... > Got caught up in graduating my youngest son from high school... :-) > > I've added your e-mail to the bug report. > > Replies emedded below: > > On 5/22/14 2:31 AM, Robert Gibson wrote: >> Hello, >> Please excuse me contacting you directly like this, > > Thanks for contacting us directly. I had originally written a test > that simply verified that "- locked" only appeared in one of the two > contending thread's stack traces. After getting this e-mail, I went > back and added more sanity checks to the test for both the stack > trace "header line" and the stack trace "thread state". > > Check out the latest version of the fix: > > http://cr.openjdk.java.net/~dcubed/8036823-webrev/2-jdk9-hs-rt/ > > The test is a bit gnarly, but it should make it clear what I expected > to see in a stack trace. > >> but I'm the reporter of JDK-8036823 and I don't have comment rights in the OpenJDK bug system. > > I suspect that you have to have an OpenJDK user name to get writable > access to the OpenJDK bug system. > >> I see you have been hard at work! > > Thanks! We have been trying very hard to get this right. > >> I'm trying to understand what I should expect to see after your proposed fix. If I have followed correctly, your proposed fix would ensure that lock information in the stack is always accurate (two threads will never both report that they have locked the same object) > > Right. The goal of the fix is to make sure that "- locked" is only > reported for one of a contended group of threads. > >> at the cost of potentially misleading information in the thread header during the transition BLOCKED->RUNNABLE. > > The potential for misleading info in the stack trace header line and > in the stack trace thread state line has always been there during > the waiting-to-lock -> locked transition. The internal 'thread state' > info is managed by helper objects that are involved in the safepoint > protocol. After a thread has successfully entered a monitor, we have > to update the internal 'thread state' info from 'blocked' -> '!blocked'. > Part of the protocol during such a transition is to check for a safepoint > and if a safepoint has started, then we pause the transition from the > 'blocked' state to the '!blocked' state. Safepoints are also when thread > dumps are generated so that's why you can see the monitor as '- locked' > and the thread as still blocked. > > I've added a comment to the code to explain all this: > > src/share/vm/runtime/objectMonitor.cpp: > > 387 Self->set_current_pending_monitor(NULL); > 388 > 389 // We cleared the pending monitor info since we've just gotten past > 390 // the enter-check-for-suspend dance and we now own the monitor free > 391 // and clear, i.e., it is no longer pending. The ThreadBlockInVM > 392 // destructor can go to a safepoint at the end of this block. If we > 393 // do a thread dump during that safepoint, then this thread will show > 394 // as having "-locked" the monitor, but the OS and java.lang.Thread > 395 // states will still report that the thread is blocked trying to > 396 // acquire it. > 397 } > >> What about the transition RUNNABLE->BLOCKED, is this similar? That is, can we see 'waiting to acquire' in the stack and 'RUNNABLE' in the header? > > I don't think so. Part of the machinery that gets the VM into the > state of 'waiting to acquire' a monitor includes creating the helper > objects that manage the internal thread state. The ThreadBlockInVM > helper object is created before we block on trying to acquire the > monitor so the thread will be considered 'blocked' before anything > else can see that we're trying to acquire the monitor. > > >> And can I assume that while releasing a lock there will not be a symmetrical problem, since the thread stays RUNNABLE when releasing a lock? > > Right. Releasing a lock isn't a blockable operation so there > should be no internal thread state changes there. > >> Thanks for any enlightenment you can bring - me and JVM stack traces have a bit of a history of mistrust (e.g. JDK-6898828)! > > Wow! I saw that bug when it was submitted in late 2009 and moved it > from "hotspot/jvmti" -> "jdk/profiling". Looks like I even wrote > a bit of an evaluation trying to explain why thread dump isn't an > accurate way of profiling. Brings back memories! > > Dan > >> Robert
29-05-2014

E-mail from the submitter: On 5/22/14 2:31 AM, Robert Gibson wrote: > Hello, > Please excuse me contacting you directly like this, but I'm the reporter of JDK-8036823 and I > don't have comment rights in the OpenJDK bug system. I see you have been hard at work! > > I'm trying to understand what I should expect to see after your proposed fix. If I have followed > correctly, your proposed fix would ensure that lock information in the stack is always accurate > (two threads will never both report that they have locked the same object) at the cost of potentially > misleading information in the thread header during the transition BLOCKED->RUNNABLE. What > about the transition RUNNABLE->BLOCKED, is this similar? That is, can we see 'waiting to acquire' > in the stack and 'RUNNABLE' in the header? And can I assume that while releasing a lock there will > not be a symmetrical problem, since the thread stays RUNNABLE when releasing a lock? > > Thanks for any enlightenment you can bring - me and JVM stack traces have a bit of a history of > mistrust (e.g. JDK-6898828)! > Robert
29-05-2014

This is is the basic issue that the different kinds of thread-state get modified at different layers in the call stack, not atomically in one go, so they can be inconsistent with each other if a dump is taken during the transitions. I think it would suffice to say: + // We cleared the pending monitor info since we've just gotten past + // the enter-check-for-suspend dance and we now own the monitor free + // and clear, i.e., it is no longer pending. The ThreadBlockInVM + // destructor can go to a safepoint at the end of this block. If we + // do a thread dump during that safepoint, then this thread will show + // as having "-locked" the monitor, but the OS and java.lang.Thread states + // will still report that the thread is blocked trying to acquire it.
21-05-2014

I nailed the 'strangeness' down to the ThreadBlockInVM helper object. It can go to a safepoint during the destructor which permits the thread dump to happen in the intermediate state. I experimented with 'fixing' it, but that causes worse problems. I have this for my proposed comment: diff -r 9c47176726c1 src/share/vm/runtime/objectMonitor.cpp --- a/src/share/vm/runtime/objectMonitor.cpp +++ b/src/share/vm/runtime/objectMonitor.cpp @@ -385,6 +385,33 @@ void ATTR ObjectMonitor::enter(TRAPS) { jt->java_suspend_self(); } Self->set_current_pending_monitor(NULL); + + // We cleared the pending monitor info since we've just gotten past + // the enter-check-for-suspend dance and we now own the monitor free + // and clear, i.e., it is no longer pending. The ThreadBlockInVM + // destructor can go to a safepoint at the end of this block. If we + // do a thread dump during that safepoint, then this monitor will + // show up like this: + // + // "Thread-0" #21 prio=5 os_prio=64 tid=0x0000000000768000 nid=0x2f waiting for monitor entry [0xfffffd7fc1111000] + // java.lang.Thread.State: BLOCKED (on object monitor) + // at TestMonitorContention$1.run(TestMonitorContention.java:6) + // - locked <0xfffffd7e6a28e0b8> (a TestMonitorContention$1) + // + // The '- locked' part correctly shows that the monitor is locked, + // but the header line shows 'waiting for monitor entry' and the + // thread state line shows 'BLOCKED (on object monitor)'. This is + // very confusing, but the alternative of clearing the pending + // monitor info after ThreadBlockInVM is destroyed would cause + // '- waiting to lock' to be shown instead. That would make it + // look like the monitor isn't owned by any thread. + // + // Consider a debugging scenario where you suspend a thread and + // leave it suspended while you let the other threads run. It's + // safe to leave that thread suspended because it doesn't own any + // monitors, right? The other threads run and eventually block + // on the monitor, but you can't see that any thread owns the + // monitor. Very confusing and now you can't debug the program. } Atomic::dec_ptr(&_count);
21-05-2014

Dan: do you see the strangeness with -Xint? Surprising that JDK 6 shows no failures given it lacks the original fix for this issue - JDK-6471736. Otherwise your suggested fix seems reasonable to me.
21-05-2014

I'm working on a more strict version of the test that checks more of the thread dump output. With the fix in place, I'm seeing some other strange things: "Thread-1" #19 prio=5 os_prio=64 tid=0x00000000007a4800 nid=0x23 waiting for monitor entry [0xffff80ffb8b87000] java.lang.Thread.State: BLOCKED (on object monitor) at TestMonitorContention$1.run(TestMonitorContention.java:6) - waiting to lock <0x000000076ac59e20> (a TestMonitorContention$1) at java.lang.Thread.run(Thread.java:745) "Thread-0" #18 prio=5 os_prio=64 tid=0x00000000007a3000 nid=0x22 waiting for monitor entry [0xffff80ffb8c88000] java.lang.Thread.State: BLOCKED (on object monitor) at TestMonitorContention$1.run(TestMonitorContention.java:6) - locked <0x000000076ac59e20> (a TestMonitorContention$1) at java.lang.Thread.run(Thread.java:745) Thread-1 is 'waiting to lock' on the stack and Thread0 is 'locked' on the stack so that's all good. However, Thread-1 is also: "Thread-0" #18 prio=5 os_prio=64 tid=0x00000000007a3000 nid=0x22 waiting for monitor entry [0xffff80ffb8c88000] java.lang.Thread.State: BLOCKED (on object monitor) which is a bit surprising. I'm expecting lines like: "Thread-1" #19 prio=5 os_prio=64 tid=0x000000000079c000 nid=0x23 runnable [0xffff80ffb8b87000] java.lang.Thread.State: RUNNABLE
20-05-2014

Attached the test (renamed from the submitter's version): $ unzip -l TestMonitorContention.zip Archive: TestMonitorContention.zip Length Date Time Name --------- ---------- ----- ---- 357 05-20-2014 13:35 TestMonitorContention.java 1580 05-20-2014 14:21 do_TestMonitorContention.ksh --------- ------- 1937 2 files
20-05-2014

Created a wrapper around the submitter's test program and ran it on various JDK versions. $ ksh do_TestMonitorContention.ksh /java/re/jdk/1.6.0/latest/binaries/solaris-i586 15 java version "1.6.0" Java(TM) SE Runtime Environment (build 1.6.0-b105) Java HotSpot(TM) Server VM (build 1.6.0-b105, mixed mode) PASSED runs: 15 $ ksh do_TestMonitorContention.ksh /java/re/jdk/1.7.0/latest/binaries/solaris-i586 15 java version "1.7.0" Java(TM) SE Runtime Environment (build 1.7.0-b147) Java HotSpot(TM) Server VM (build 21.0-b17, mixed mode) PASSED runs: 6 FAILED runs: 9 $ ksh do_TestMonitorContention.ksh /java/re/jdk/1.8.0/latest/binaries/solaris-x64 15 java version "1.8.0" Java(TM) SE Runtime Environment (build 1.8.0-b132) Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode) PASSED runs: 4 FAILED runs: 11 $ ksh do_TestMonitorContention.ksh /java/re/jdk/1.9.0/latest/binaries/solaris-x64 15 java version "1.9.0-ea" Java(TM) SE Runtime Environment (build 1.9.0-ea-b13) Java HotSpot(TM) 64-Bit Server VM (build 1.9.0-ea-b13, mixed mode) PASSED runs: 2 FAILED runs: 13 The bug does not reproduce using 1.6.0-b105. It does reproduce in 1.7.0, 1.8.0 and the current 1.9.0. Here's the same test run on the proposed fix: $ ksh do_TestMonitorContention.ksh jdk_fixed 15 java version "1.9.0-ea" Java(TM) SE Runtime Environment (build 1.9.0-ea-b13) Java HotSpot(TM) 64-Bit Server VM (build 1.9.0-internal-201405201833.ddaugher.8036823_exp_for_jd, mixed mode) PASSED runs: 15
20-05-2014

This might do it: diff -r e4d54c03efe7 src/share/vm/runtime/vframe.cpp --- a/src/share/vm/runtime/vframe.cpp Sat May 17 19:34:38 2014 -0400 +++ b/src/share/vm/runtime/vframe.cpp Tue May 20 11:27:49 2014 -0700 @@ -199,6 +199,7 @@ void javaVFrame::print_lock_info_on(outp continue; } if (monitor->owner() != NULL) { + // the monitor is associated with an object, i.e., it is locked // First, assume we have the monitor locked. If we haven't found an // owned monitor before and this is the first frame, then we need to @@ -209,7 +210,11 @@ void javaVFrame::print_lock_info_on(outp if (!found_first_monitor && frame_count == 0) { markOop mark = monitor->owner()->mark(); if (mark->has_monitor() && - mark->monitor() == thread()->current_pending_monitor()) { + ( // we have marked ourself as pending on this monitor + mark->monitor() == thread()->current_pending_monitor() || + // we are not the owner of this monitor + !mark->monitor()->is_entered(thread()) + )) { lock_state = "waiting to lock"; } } Checking it out now.
20-05-2014

This bug came up in July of 2012 in these two e-mail threads: http://mail.openjdk.java.net/pipermail/hotspot-dev/2012-July/006170.html http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2012-July/004106.html
20-05-2014

Dan: right. The new clause catches the case that the objectMonitor change was also trying to catch. That said, after further thought I can't see why we can't indeed use the simple check of the owner: + if (mark->has_monitor() && mark->monitor()->owner() != thread()) { lock_state = "waiting to lock"; } with a comment perhaps that the monitor either is, or is in the process of being, set as the pending monitor for this thread.
17-05-2014

If we add the owner check as the third clause in the report routine, Zhengyu's proposed change to objectMonitor.cpp should _not_ be needed. The existing pending monitor check would catch the post-ThreadBlockedInVM safepoint cases and the owner check would catch the safepoint in ThreadBlockedInVM case.
16-05-2014

If pending_monitor check is still needed, my early patch on objectMonitor.cpp is needed. The later patch seems to result correct lock state, and only touches a report routine, which seems to me is a lot less risky than modifying objectMonitor::enter(), unless there is a reason otherwise.
16-05-2014

I added the check for the pending_monitor under JDK-6471736. I have a recollection of there being a reason we could not necessarily check the owner value when deciding if the monitor was locked or in the process of being locked. Perhaps we should add the owner check as a third clause to supplement the pending_monitor check rather than replace it? Update: I checked my archives and the original discussion of this was quite simple. No mention was ever made of checking the owner field - so I have to wonder why as it now seems so "obvious" ??
16-05-2014

Another solution, suggested by David Holmes, is more straight forward. By comparing the monitor owner against current thread, should find out if the thread is waiting for lock or already owning the lock. diff --git a/src/share/vm/runtime/vframe.cpp b/src/share/vm/runtime/vframe.cpp --- a/src/share/vm/runtime/vframe.cpp +++ b/src/share/vm/runtime/vframe.cpp @@ -208,8 +208,7 @@ const char *lock_state = "locked"; // assume we have the monitor locked if (!found_first_monitor && frame_count == 0) { markOop mark = monitor->owner()->mark(); - if (mark->has_monitor() && - mark->monitor() == thread()->current_pending_monitor()) { + if (mark->has_monitor() && mark->monitor()->owner() != thread()) { lock_state = "waiting to lock"; } }
15-05-2014

I haven't nailed it down yet, but I think the StackFrameInfo class is getting the list of locked_monitors wrong. I think it's presuming that a monitor on the Java stack means that the thread has it locked.
15-05-2014

Just trying to understand the issue here. Based on this test in the description section: > ACTUAL - > A thread that is shows 'waiting for monitor entry' in its stack trace header sometimes > shows 'locked' on the object it is supposedly waiting to lock. See Thread-0 in the > attached stack trace We have these two stack snippets: "Thread-1" #9 prio=5 os_prio=0 tid=0x14d0b800 nid=0x1474 runnable [0x1554f000] java.lang.Thread.State: RUNNABLE at Test$1.run(Test.java:6) - locked <0x048725f8> (a Test$1) at java.lang.Thread.run(Thread.java:744) "Thread-0" #8 prio=5 os_prio=0 tid=0x14d09000 nid=0x2f4c waiting for monitor entry [0x1503f000] java.lang.Thread.State: BLOCKED (on object monitor) at Test$1.run(Test.java:6) - locked <0x048725f8> (a Test$1) at java.lang.Thread.run(Thread.java:744) Based on the info above, I would conclude that "Thread-1" owns the monitor (0x048725f8) and is RUNNABLE. I would also conclude that "Thread-0" is "waiting for monitor entry" and is "BLOCKED (on object monitor)" and the monitor that "Thread-0" is blocked on is 0x048725f8. I agree that the "locked" part of this line is a bit confusing: - locked <0x048725f8> (a Test$1) when looked at by itself. However, when combined with the other info in that stack trace... BUT, I've probably been looking at stack trace snippets like this for way too long... and I've gotten used to ignoring that wierdness.
15-05-2014

This is not rare racing problem, it is very reproducible. The cause is due to logic in ObjectMonitor::enter(TRAPS) (objectMonitor.cpp) around line #360 When the thread tries to transition to blocked-in-vm state, it is blocked by safepoint, from where the stack dump is printed. But at this time, thread's current pending monitor is not set, which causes the thread thinks it owns the monitor. Following patch fixes this problem, but not sure if there are any side-effects. More tests are needed. diff -r 722198b9fa26 src/share/vm/runtime/objectMonitor.cpp --- a/src/share/vm/runtime/objectMonitor.cpp Mon May 12 20:25:53 2014 -0400 +++ b/src/share/vm/runtime/objectMonitor.cpp Wed May 14 10:52:20 2014 -0400 @@ -358,9 +358,11 @@ } OSThreadContendState osts(Self->osthread()); + + Self->set_current_pending_monitor(this); <=== move here fixes the problem ThreadBlockInVM tbivm(jt); - Self->set_current_pending_monitor(this); +// Self->set_current_pending_monitor(this); <=== original // TODO-FIXME: change the following for(;;) loop to straight-line code. for (;;) {
14-05-2014

Runtime is the correct place for issues with threading and synchronization, including stack-trace info related thereto. This definitely looks like a bug. Possibly caused by the thread releasing the lock not getting the chance to update the local state to show it is unlocked before the stackdump request hits.
07-03-2014

Not sure what subcomponent this should be, guessing Runtime. Inconsistent stack traces are a common issue on the mailing lists. Having two threads "locked" on the same lock is clearly confusing.
06-03-2014