pdeva
pdeva

Reputation: 45531

Highly unusual situation - Thread blocked on a lock which it is holding?

This java program I am working on seems to hang on startup, so I tried using jconsole to debug the problem. As it turns out it is waiting on a call to a method which is declared as -

synchronized void stopQuery()

But here is the crazy part, the lock for the 'synchronized' method is already held by the thread which is blocked for it. I have attached a screenshot from JConsole after executing the getThreadInfo() MXBean method.

Notice that the lockOwnerId and threadId are same! How is this even possible?

alt text

Edit:
Link to one of the stack traces of this situation. Note that after looking at the stacktrace it might appear that even the 'org.eclipse.jdt.internal.ui.text.JavaReconciler' thread is trying to lock on to the same DiskIndex object, but if you look at the object address you will see that it is in fact a different DiskIndex object.

Edit 2:
Another Link to a different stacktrace I obtained when I reproduced this problem. It should be helpful to compare the two to see what is common.

Upvotes: 4

Views: 8682

Answers (5)

Bob Cross
Bob Cross

Reputation: 22312

This looks like a particularly nasty deadlock. It's hard to tell for sure without a little more information. Here's what I see without the code in front of me, though:

Possible deadlock on (or at least contention for) Object reference 0x00002aace2276720 between "Text Viewer Hover Presenter" and "Worker-3" while "Worker-3" is holding the lock on reference 0x00002aace2276ad0.

This second reference seems to be the cause for a whole pile of blocked threads (specifically "Worker-4", "Worker-1" and "Worker-0").

My suggestion would be to check ASTProvider.java line 450 (see the stack trace for the first two where the suspicious object lock seems to be held but then doesn't seem to get past the wait()). I would also suggest try running the executable locked to a single core (assuming that this is a multicore system).

The next piece of code that looks like it's worth testing would be SelectionListenerWithASTManager.java line 153 (where reference 0x00002aace2276ad0 is locked, causing the Workers to block).

Lockers of 0x00002aace2276720:

"Text Viewer Hover Presenter" daemon prio=10 tid=0x00002aad20166400 nid=0x51f4 in Object.wait() [0x000000004254c000..0x000000004254dd90]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00002aace2276720> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:485)
    at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider.getAST(ASTProvider.java:450)
    - locked <0x00002aace2276720> (a java.lang.Object)
    at org.eclipse.jdt.ui.SharedASTProvider.getAST(SharedASTProvider.java:129)
    at org.eclipse.jdt.internal.ui.text.java.hover.NLSStringHover.getHoverInfo(NLSStringHover.java:87)
    at org.eclipse.jdt.internal.ui.text.java.hover.AbstractJavaEditorTextHover.getHoverInfo2(AbstractJavaEditorTextHover.java:86)
    at org.eclipse.jdt.internal.ui.text.java.hover.BestMatchHover.getHoverInfo2(BestMatchHover.java:129)
    at org.eclipse.jdt.internal.ui.text.java.hover.JavaEditorTextHoverProxy.getHoverInfo2(JavaEditorTextHoverProxy.java:82)
    at org.eclipse.jface.text.TextViewerHoverManager$4.run(TextViewerHoverManager.java:166)

"Worker-3" prio=10 tid=0x00002aad132c3800 nid=0x5166 in Object.wait() [0x0000000042249000..0x000000004224ab10]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00002aace2276720> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:485)
    at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider.getAST(ASTProvider.java:450)
    - locked <0x00002aace2276720> (a java.lang.Object)
    at org.eclipse.jdt.ui.SharedASTProvider.getAST(SharedASTProvider.java:129)
    at org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager$PartListenerGroup.calculateASTandInform(SelectionListenerWithASTManager.java:168)
    at org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager$3.run(SelectionListenerWithASTManager.java:153)
    - locked <0x00002aace2276ad0> (a java.lang.Object)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)

Blocked on 0x00002aace2276ad0

"Worker-4" prio=10 tid=0x00002aad132c4000 nid=0x5167 waiting for monitor entry [0x000000004234b000..0x000000004234bc90]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager$3.run(SelectionListenerWithASTManager.java:153)
    - waiting to lock <0x00002aace2276ad0> (a java.lang.Object)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)

"Worker-1" prio=10 tid=0x00002aad12835800 nid=0x5164 waiting for monitor entry [0x0000000041a42000..0x0000000041a42a10]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager$3.run(SelectionListenerWithASTManager.java:153)
    - waiting to lock <0x00002aace2276ad0> (a java.lang.Object)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)

"Worker-0" prio=10 tid=0x00002aad11a0ac00 nid=0x5146 waiting for monitor entry [0x0000000041941000..0x0000000041941d90]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager$3.run(SelectionListenerWithASTManager.java:153)
    - waiting to lock <0x00002aace2276ad0> (a java.lang.Object)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)

Upvotes: 2

Aaron Digulla
Aaron Digulla

Reputation: 328760

Is it possible that DiskIndex.java has no line information? My guess is that you're hanging inside the method where it tries to acquire a completely different lock but you can't see that because there is no line information to display in the stack trace.

Upvotes: 0

Chris Kimpton
Chris Kimpton

Reputation: 5541

It might be worth trying a deadlock detecting bit of code - like this.

The stopQuery lock does not seem to have acquired the lock previously in the stack trace, but then that lock does not seem to have acquired anywhere else either - weird...

"Worker-2" prio=10 tid=0x00002aad1da66400 nid=0x5165 waiting for monitor entry [0x0000000041b43000..0x0000000041b43b90]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.eclipse.jdt.internal.core.index.DiskIndex.stopQuery(DiskIndex.java)
    - waiting to lock <0x00002aacdfe83ea8> (a org.eclipse.jdt.internal.core.index.DiskIndex)
    at org.eclipse.jdt.internal.core.index.Index.stopQuery(Index.java:192)

There is a wait on a held lock in this bit, but thats released the lock until it gets a notify/timeout:

"Text Viewer Hover Presenter" daemon prio=10 tid=0x00002aad20166400 nid=0x51f4 in Object.wait() [0x000000004254c000..0x000000004254dd90]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00002aace2276720> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:485)
    at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider.getAST(ASTProvider.java:450)
    - locked <0x00002aace2276720> (a java.lang.Object)
    at org.eclipse.jdt.ui.SharedASTProvider.getAST(SharedASTProvider.java:129)
    at org.eclipse.jdt.internal.ui.text.java.hover.NLSStringHover.getHoverInfo(NLSStringHover.java:87)
    at org.eclipse.jdt.internal.ui.text.java.hover.AbstractJavaEditorTextHover.getHoverInfo2(AbstractJavaEditorTextHover.java:86)
    at org.eclipse.jdt.internal.ui.text.java.hover.BestMatchHover.getHoverInfo2(BestMatchHover.java:129)
    at org.eclipse.jdt.internal.ui.text.java.hover.JavaEditorTextHoverProxy.getHoverInfo2(JavaEditorTextHoverProxy.java:82)
    at org.eclipse.jface.text.TextViewerHoverManager$4.run(TextViewerHoverManager.java:166)

Upvotes: 0

pdeva
pdeva

Reputation: 45531

but locks on synchronized methods are reentrant, which means that if a thread which holds the lock on that object tries to lock it again, it will always succeed.

Upvotes: 0

Carl Seleborg
Carl Seleborg

Reputation: 13305

Is the method recursive, somehow? Maybe you're using an object inside of it which requires that very same method?

Upvotes: 0

Related Questions