annotate agent/src/share/classes/sun/jvm/hotspot/runtime/DeadlockDetector.java @ 12226:7944aba7ba41

8015107: NPG: Use consistent naming for metaspace concepts Reviewed-by: coleenp, mgerdin, hseigel
author ehelin
date Mon, 12 Aug 2013 17:37:02 +0200
parents c18cbe5936b8
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
2 * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 package sun.jvm.hotspot.runtime;
a61af66fc99e Initial load
duke
parents:
diff changeset
26
a61af66fc99e Initial load
duke
parents:
diff changeset
27 import sun.jvm.hotspot.debugger.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
28 import sun.jvm.hotspot.memory.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
29 import sun.jvm.hotspot.oops.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
30 import java.io.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
31 import java.util.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
32 import java.util.Map.Entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
33
a61af66fc99e Initial load
duke
parents:
diff changeset
34 /** Prints information about Java-level deadlocks in supplied 'tty'. */
a61af66fc99e Initial load
duke
parents:
diff changeset
35
a61af66fc99e Initial load
duke
parents:
diff changeset
36 public class DeadlockDetector {
a61af66fc99e Initial load
duke
parents:
diff changeset
37
a61af66fc99e Initial load
duke
parents:
diff changeset
38 public static void print(PrintStream tty) {
a61af66fc99e Initial load
duke
parents:
diff changeset
39 print(tty, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
40 }
a61af66fc99e Initial load
duke
parents:
diff changeset
41
a61af66fc99e Initial load
duke
parents:
diff changeset
42 /** prints zero or more deadlocks into 'tty' taking current
a61af66fc99e Initial load
duke
parents:
diff changeset
43 snapshot of Java threads and locks */
a61af66fc99e Initial load
duke
parents:
diff changeset
44 public static void print(PrintStream tty, boolean concurrentLocks) {
a61af66fc99e Initial load
duke
parents:
diff changeset
45 tty.println("Deadlock Detection:");
a61af66fc99e Initial load
duke
parents:
diff changeset
46 tty.println();
a61af66fc99e Initial load
duke
parents:
diff changeset
47
a61af66fc99e Initial load
duke
parents:
diff changeset
48 int globalDfn = 0, thisDfn;
a61af66fc99e Initial load
duke
parents:
diff changeset
49 int numberOfDeadlocks = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
50 JavaThread currentThread = null, previousThread = null;
a61af66fc99e Initial load
duke
parents:
diff changeset
51 ObjectMonitor waitingToLockMonitor = null;
a61af66fc99e Initial load
duke
parents:
diff changeset
52 Oop waitingToLockBlocker = null;
a61af66fc99e Initial load
duke
parents:
diff changeset
53
a61af66fc99e Initial load
duke
parents:
diff changeset
54 threads = VM.getVM().getThreads();
a61af66fc99e Initial load
duke
parents:
diff changeset
55 heap = VM.getVM().getObjectHeap();
a61af66fc99e Initial load
duke
parents:
diff changeset
56 createThreadTable();
a61af66fc99e Initial load
duke
parents:
diff changeset
57
a61af66fc99e Initial load
duke
parents:
diff changeset
58 Iterator i = threadTable.entrySet().iterator();
a61af66fc99e Initial load
duke
parents:
diff changeset
59 while (i.hasNext()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
60 Entry e = (Entry)i.next();
a61af66fc99e Initial load
duke
parents:
diff changeset
61 if (dfn(e) >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
62 // this thread was already visited
a61af66fc99e Initial load
duke
parents:
diff changeset
63 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
64 }
a61af66fc99e Initial load
duke
parents:
diff changeset
65
a61af66fc99e Initial load
duke
parents:
diff changeset
66 thisDfn = globalDfn;
a61af66fc99e Initial load
duke
parents:
diff changeset
67 JavaThread thread = (JavaThread)e.getKey();
a61af66fc99e Initial load
duke
parents:
diff changeset
68 previousThread = thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
69
a61af66fc99e Initial load
duke
parents:
diff changeset
70 // When there is a deadlock, all the monitors involved in the dependency
a61af66fc99e Initial load
duke
parents:
diff changeset
71 // cycle must be contended and heavyweight. So we only care about the
a61af66fc99e Initial load
duke
parents:
diff changeset
72 // heavyweight monitor a thread is waiting to lock.
a61af66fc99e Initial load
duke
parents:
diff changeset
73 try {
a61af66fc99e Initial load
duke
parents:
diff changeset
74 waitingToLockMonitor = thread.getCurrentPendingMonitor();
a61af66fc99e Initial load
duke
parents:
diff changeset
75 } catch (RuntimeException re) {
a61af66fc99e Initial load
duke
parents:
diff changeset
76 tty.println("This version of HotSpot VM doesn't support deadlock detection.");
a61af66fc99e Initial load
duke
parents:
diff changeset
77 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
78 }
a61af66fc99e Initial load
duke
parents:
diff changeset
79
a61af66fc99e Initial load
duke
parents:
diff changeset
80 Klass abstractOwnableSyncKlass = null;
a61af66fc99e Initial load
duke
parents:
diff changeset
81 if (concurrentLocks) {
a61af66fc99e Initial load
duke
parents:
diff changeset
82 waitingToLockBlocker = thread.getCurrentParkBlocker();
a61af66fc99e Initial load
duke
parents:
diff changeset
83 SystemDictionary sysDict = VM.getVM().getSystemDictionary();
a61af66fc99e Initial load
duke
parents:
diff changeset
84 abstractOwnableSyncKlass = sysDict.getAbstractOwnableSynchronizerKlass();
a61af66fc99e Initial load
duke
parents:
diff changeset
85 }
a61af66fc99e Initial load
duke
parents:
diff changeset
86
a61af66fc99e Initial load
duke
parents:
diff changeset
87 while (waitingToLockMonitor != null ||
a61af66fc99e Initial load
duke
parents:
diff changeset
88 waitingToLockBlocker != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
89 if (waitingToLockMonitor != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
90 currentThread = threads.owningThreadFromMonitor(waitingToLockMonitor);
a61af66fc99e Initial load
duke
parents:
diff changeset
91 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
92 if (concurrentLocks) {
a61af66fc99e Initial load
duke
parents:
diff changeset
93 if (waitingToLockBlocker.isA(abstractOwnableSyncKlass)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
94 Oop threadOop = OopUtilities.abstractOwnableSynchronizerGetOwnerThread(waitingToLockBlocker);
a61af66fc99e Initial load
duke
parents:
diff changeset
95 if (threadOop != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
96 currentThread = OopUtilities.threadOopGetJavaThread(threadOop);
a61af66fc99e Initial load
duke
parents:
diff changeset
97 }
a61af66fc99e Initial load
duke
parents:
diff changeset
98 }
a61af66fc99e Initial load
duke
parents:
diff changeset
99 }
a61af66fc99e Initial load
duke
parents:
diff changeset
100 }
a61af66fc99e Initial load
duke
parents:
diff changeset
101 if (currentThread == null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // No dependency on another thread
a61af66fc99e Initial load
duke
parents:
diff changeset
103 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
104 }
a61af66fc99e Initial load
duke
parents:
diff changeset
105 if (dfn(currentThread) < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
106 // First visit to this thread
a61af66fc99e Initial load
duke
parents:
diff changeset
107 threadTable.put(currentThread, new Integer(globalDfn++));
a61af66fc99e Initial load
duke
parents:
diff changeset
108 } else if (dfn(currentThread) < thisDfn) {
a61af66fc99e Initial load
duke
parents:
diff changeset
109 // Thread already visited, and not on a (new) cycle
a61af66fc99e Initial load
duke
parents:
diff changeset
110 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
111 } else if (currentThread == previousThread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
112 // Self-loop, ignore
a61af66fc99e Initial load
duke
parents:
diff changeset
113 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
114 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
115 // We have a (new) cycle
a61af66fc99e Initial load
duke
parents:
diff changeset
116 numberOfDeadlocks ++;
a61af66fc99e Initial load
duke
parents:
diff changeset
117 printOneDeadlock(tty, currentThread, concurrentLocks);
a61af66fc99e Initial load
duke
parents:
diff changeset
118 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
119 }
a61af66fc99e Initial load
duke
parents:
diff changeset
120 previousThread = currentThread;
a61af66fc99e Initial load
duke
parents:
diff changeset
121 waitingToLockMonitor = (ObjectMonitor)currentThread.getCurrentPendingMonitor();
a61af66fc99e Initial load
duke
parents:
diff changeset
122 if (concurrentLocks) {
a61af66fc99e Initial load
duke
parents:
diff changeset
123 waitingToLockBlocker = currentThread.getCurrentParkBlocker();
a61af66fc99e Initial load
duke
parents:
diff changeset
124 }
a61af66fc99e Initial load
duke
parents:
diff changeset
125 }
a61af66fc99e Initial load
duke
parents:
diff changeset
126 }
a61af66fc99e Initial load
duke
parents:
diff changeset
127
a61af66fc99e Initial load
duke
parents:
diff changeset
128 switch (numberOfDeadlocks) {
a61af66fc99e Initial load
duke
parents:
diff changeset
129 case 0:
a61af66fc99e Initial load
duke
parents:
diff changeset
130 tty.println("No deadlocks found.");
a61af66fc99e Initial load
duke
parents:
diff changeset
131 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
132 case 1:
a61af66fc99e Initial load
duke
parents:
diff changeset
133 tty.println("Found a total of 1 deadlock.");
a61af66fc99e Initial load
duke
parents:
diff changeset
134 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
135 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
136 tty.println("Found a total of " + numberOfDeadlocks + " deadlocks.");
a61af66fc99e Initial load
duke
parents:
diff changeset
137 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
139 tty.println();
a61af66fc99e Initial load
duke
parents:
diff changeset
140 }
a61af66fc99e Initial load
duke
parents:
diff changeset
141
a61af66fc99e Initial load
duke
parents:
diff changeset
142 //-- Internals only below this point
a61af66fc99e Initial load
duke
parents:
diff changeset
143 private static Threads threads;
a61af66fc99e Initial load
duke
parents:
diff changeset
144 private static ObjectHeap heap;
a61af66fc99e Initial load
duke
parents:
diff changeset
145 private static HashMap threadTable;
a61af66fc99e Initial load
duke
parents:
diff changeset
146
a61af66fc99e Initial load
duke
parents:
diff changeset
147 private static void createThreadTable() {
a61af66fc99e Initial load
duke
parents:
diff changeset
148 threadTable = new HashMap();
a61af66fc99e Initial load
duke
parents:
diff changeset
149 for (JavaThread cur = threads.first(); cur != null; cur = cur.next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
150 // initialize dfn for each thread to -1
a61af66fc99e Initial load
duke
parents:
diff changeset
151 threadTable.put(cur, new Integer(-1));
a61af66fc99e Initial load
duke
parents:
diff changeset
152 }
a61af66fc99e Initial load
duke
parents:
diff changeset
153 }
a61af66fc99e Initial load
duke
parents:
diff changeset
154
a61af66fc99e Initial load
duke
parents:
diff changeset
155 private static int dfn(JavaThread thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
156 Object obj = threadTable.get(thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
157 if (obj != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
158 return ((Integer)obj).intValue();
a61af66fc99e Initial load
duke
parents:
diff changeset
159 }
a61af66fc99e Initial load
duke
parents:
diff changeset
160 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
162
a61af66fc99e Initial load
duke
parents:
diff changeset
163 private static int dfn(Entry e) {
a61af66fc99e Initial load
duke
parents:
diff changeset
164 return ((Integer)e.getValue()).intValue();
a61af66fc99e Initial load
duke
parents:
diff changeset
165 }
a61af66fc99e Initial load
duke
parents:
diff changeset
166
a61af66fc99e Initial load
duke
parents:
diff changeset
167 private static void printOneDeadlock(PrintStream tty, JavaThread thread,
a61af66fc99e Initial load
duke
parents:
diff changeset
168 boolean concurrentLocks) {
a61af66fc99e Initial load
duke
parents:
diff changeset
169 tty.println("Found one Java-level deadlock:");
a61af66fc99e Initial load
duke
parents:
diff changeset
170 tty.println("=============================");
a61af66fc99e Initial load
duke
parents:
diff changeset
171 ObjectMonitor waitingToLockMonitor = null;
a61af66fc99e Initial load
duke
parents:
diff changeset
172 Oop waitingToLockBlocker = null;
a61af66fc99e Initial load
duke
parents:
diff changeset
173 JavaThread currentThread = thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
174 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
175 tty.println();
a61af66fc99e Initial load
duke
parents:
diff changeset
176 tty.println("\"" + currentThread.getThreadName() + "\":");
a61af66fc99e Initial load
duke
parents:
diff changeset
177 waitingToLockMonitor = currentThread.getCurrentPendingMonitor();
a61af66fc99e Initial load
duke
parents:
diff changeset
178 if (waitingToLockMonitor != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
179 tty.print(" waiting to lock Monitor@" + waitingToLockMonitor.getAddress());
a61af66fc99e Initial load
duke
parents:
diff changeset
180 OopHandle obj = waitingToLockMonitor.object();
a61af66fc99e Initial load
duke
parents:
diff changeset
181 Oop oop = heap.newOop(obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
182 if (obj != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
183 tty.print(" (Object@");
a61af66fc99e Initial load
duke
parents:
diff changeset
184 Oop.printOopAddressOn(oop, tty);
a61af66fc99e Initial load
duke
parents:
diff changeset
185 tty.print(", a " + oop.getKlass().getName().asString() + ")" );
a61af66fc99e Initial load
duke
parents:
diff changeset
186 tty.print(",\n which is held by");
a61af66fc99e Initial load
duke
parents:
diff changeset
187 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
188 // No Java object associated - a raw monitor
a61af66fc99e Initial load
duke
parents:
diff changeset
189 tty.print(" (raw monitor),\n which is held by");
a61af66fc99e Initial load
duke
parents:
diff changeset
190 }
a61af66fc99e Initial load
duke
parents:
diff changeset
191 currentThread = threads.owningThreadFromMonitor(waitingToLockMonitor);
a61af66fc99e Initial load
duke
parents:
diff changeset
192 tty.print(" \"" + currentThread.getThreadName() + "\"");
a61af66fc99e Initial load
duke
parents:
diff changeset
193 } else if (concurrentLocks) {
a61af66fc99e Initial load
duke
parents:
diff changeset
194 waitingToLockBlocker = currentThread.getCurrentParkBlocker();
a61af66fc99e Initial load
duke
parents:
diff changeset
195 tty.print(" waiting for ownable synchronizer ");
a61af66fc99e Initial load
duke
parents:
diff changeset
196 Oop.printOopAddressOn(waitingToLockBlocker, tty);
a61af66fc99e Initial load
duke
parents:
diff changeset
197 tty.print(", (a " + waitingToLockBlocker.getKlass().getName().asString() + ")" );
a61af66fc99e Initial load
duke
parents:
diff changeset
198 Oop threadOop = OopUtilities.abstractOwnableSynchronizerGetOwnerThread(waitingToLockBlocker);
a61af66fc99e Initial load
duke
parents:
diff changeset
199 currentThread = OopUtilities.threadOopGetJavaThread(threadOop);
a61af66fc99e Initial load
duke
parents:
diff changeset
200 tty.print(",\n which is held by");
a61af66fc99e Initial load
duke
parents:
diff changeset
201 tty.print(" \"" + currentThread.getThreadName() + "\"");
a61af66fc99e Initial load
duke
parents:
diff changeset
202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
203 } while (!currentThread.equals(thread));
a61af66fc99e Initial load
duke
parents:
diff changeset
204 tty.println();
a61af66fc99e Initial load
duke
parents:
diff changeset
205 tty.println();
a61af66fc99e Initial load
duke
parents:
diff changeset
206 }
a61af66fc99e Initial load
duke
parents:
diff changeset
207 }