Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/lang/management/ThreadMXBean/Locks.java
38821 views
1
/*
2
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/*
25
* @test
26
* @bug 4530538
27
* @summary Basic unit test of ThreadInfo.getLockName()
28
* and ThreadInfo.getLockOwnerName()
29
* @author Mandy Chung
30
* @author Jaroslav Bachorik
31
*
32
* @library /lib/testlibrary
33
* @build jdk.testlibrary.*
34
* @run main/othervm Locks
35
*/
36
37
import java.lang.management.*;
38
import java.util.concurrent.Phaser;
39
import jdk.testlibrary.LockFreeLogManager;
40
41
public class Locks {
42
private static final Object objA = new Object();
43
private static final Object objB = new Object();
44
private static final Object objC = new Object();
45
private static final ThreadMXBean tm = ManagementFactory.getThreadMXBean();
46
private static final LockFreeLogManager logger = new LockFreeLogManager();
47
48
private static boolean testFailed = false;
49
50
private static String getLockName(Object lock) {
51
if (lock == null) return null;
52
53
return lock.getClass().getName() + '@' +
54
Integer.toHexString(System.identityHashCode(lock));
55
}
56
57
private static void assertNoLock(Thread t) {
58
long tid = t.getId();
59
ThreadInfo info = tm.getThreadInfo(tid);
60
String result = info.getLockName();
61
62
if (result != null) {
63
throw new RuntimeException("Thread " + t.getName() + " is not supposed to hold any lock. " +
64
"Currently owning lock: " + result);
65
}
66
}
67
68
private static void checkBlockedObject(Thread t, Object lock, Thread owner,
69
Thread.State expectedState) {
70
long tid = t.getId();
71
ThreadInfo info = tm.getThreadInfo(tid);
72
String result = info.getLockName();
73
String expectedLock = (lock != null ? getLockName(lock) : null);
74
String expectedOwner = (owner != null ? owner.getName() : null);
75
76
if (lock != null) {
77
if (expectedState == Thread.State.BLOCKED) {
78
int retryCount=0;
79
while(info.getThreadState() != Thread.State.BLOCKED) {
80
if (retryCount++ > 500) {
81
throw new RuntimeException("Thread " + t.getName() +
82
" is expected to block on " + expectedLock +
83
" but got " + result +
84
" Thread.State = " + info.getThreadState());
85
}
86
goSleep(100);
87
info = tm.getThreadInfo(tid);
88
result = info.getLockName();
89
}
90
}
91
if (expectedState == Thread.State.WAITING &&
92
info.getThreadState() != Thread.State.WAITING) {
93
throw new RuntimeException("Thread " + t.getName() +
94
" is expected to wait on " + expectedLock +
95
" but got " + result +
96
" Thread.State = " + info.getThreadState());
97
}
98
}
99
100
if ((result != null && !result.equals(expectedLock)) ||
101
(result == null && expectedLock != null)) {
102
throw new RuntimeException("Thread " + t.getName() + " is blocked on " +
103
expectedLock + " but got " + result);
104
}
105
result = info.getLockOwnerName();
106
if ((result != null && !result.equals(expectedOwner)) ||
107
(result == null && expectedOwner != null)) {
108
throw new RuntimeException("Owner of " + lock + " should be " +
109
expectedOwner + " but got " + result);
110
}
111
}
112
113
private static void goSleep(long ms) {
114
try {
115
Thread.sleep(ms);
116
} catch (InterruptedException e) {
117
e.printStackTrace();
118
testFailed = true;
119
}
120
}
121
122
private static volatile int dummyCounter = 0;
123
124
static class LockAThread extends Thread {
125
private final Phaser p;
126
public LockAThread(Phaser p) {
127
super("LockAThread");
128
this.p = p;
129
}
130
public void run() {
131
synchronized(objA) {
132
// stop here for LockBThread to hold objB
133
log("LockAThread about to block on objB");
134
p.arriveAndAwaitAdvance(); // Phase 1 (blocking)
135
synchronized(objB) {
136
dummyCounter++;
137
};
138
}
139
p.arriveAndAwaitAdvance(); // Phase 2 (blocking)
140
log("LockAThread about to exit");
141
// Make sure the current thread is not holding any lock
142
assertNoLock(this);
143
}
144
}
145
146
static class LockBThread extends Thread {
147
private final Phaser p;
148
public LockBThread(Phaser p) {
149
super("LockBThread");
150
this.p = p;
151
}
152
public void run() {
153
synchronized(objB) {
154
log("LockBThread about to block on objC");
155
p.arriveAndAwaitAdvance(); // Phase 1 (blocking)
156
// Signal main thread about to block on objC
157
synchronized(objC) {
158
dummyCounter++;
159
};
160
}
161
p.arriveAndAwaitAdvance(); // Phase 2 (blocking)
162
log("LockBThread about to exit");
163
// Make sure the current thread is not holding any lock
164
assertNoLock(this);
165
}
166
}
167
168
private static WaitingThread waiter;
169
private static final Object ready = new Object();
170
private static CheckerThread checker;
171
static class WaitingThread extends Thread {
172
private final Phaser p;
173
174
volatile boolean waiting = false;
175
176
public WaitingThread(Phaser p) {
177
super("WaitingThread");
178
this.p = p;
179
}
180
@Override
181
public void run() {
182
synchronized(objC) {
183
log("WaitingThread about to wait on objC");
184
try {
185
// Signal checker thread, about to wait on objC.
186
waiting = false;
187
p.arriveAndAwaitAdvance(); // Phase 1 (waiting)
188
waiting = true;
189
objC.wait();
190
} catch (InterruptedException e) {
191
e.printStackTrace();
192
testFailed = true;
193
}
194
195
// block until CheckerThread finishes checking
196
log("WaitingThread about to block on ready");
197
// signal checker thread that it is about acquire
198
// object ready.
199
p.arriveAndAwaitAdvance(); // Phase 2 (waiting)
200
synchronized(ready) {
201
dummyCounter++;
202
}
203
}
204
synchronized(objC) {
205
try {
206
// signal checker thread, about to wait on objC
207
waiting = false;
208
p.arriveAndAwaitAdvance(); // Phase 3 (waiting)
209
waiting = true;
210
objC.wait();
211
} catch (InterruptedException e) {
212
e.printStackTrace();
213
testFailed = true;
214
}
215
}
216
log("WaitingThread about to exit waiting on objC 2");
217
}
218
219
public void waitForWaiting() {
220
p.arriveAndAwaitAdvance();
221
while (!waiting) {
222
goSleep(10);
223
}
224
waitForState(State.WAITING);
225
}
226
227
public void waitForBlocked() {
228
p.arriveAndAwaitAdvance();
229
waitForState(State.BLOCKED);
230
}
231
232
private void waitForState(Thread.State state) {
233
while (!waiter.isInterrupted() && waiter.getState() != state) {
234
Thread.yield();
235
}
236
}
237
}
238
static class CheckerThread extends Thread {
239
public CheckerThread() {
240
super("CheckerThread");
241
}
242
243
public void run() {
244
synchronized (ready) {
245
// wait until WaitingThread about to wait for objC
246
waiter.waitForWaiting(); // Phase 1 (waiting)
247
checkBlockedObject(waiter, objC, null, Thread.State.WAITING);
248
249
synchronized (objC) {
250
objC.notify();
251
}
252
253
// wait for waiter thread to about to enter
254
// synchronized object ready.
255
waiter.waitForBlocked(); // Phase 2 (waiting)
256
checkBlockedObject(waiter, ready, this, Thread.State.BLOCKED);
257
}
258
259
// wait for signal from waiting thread that it is about
260
// wait for objC.
261
waiter.waitForWaiting(); // Phase 3 (waiting)
262
synchronized(objC) {
263
checkBlockedObject(waiter, objC, Thread.currentThread(), Thread.State.WAITING);
264
objC.notify();
265
}
266
267
}
268
}
269
270
public static void main(String args[]) throws Exception {
271
Thread mainThread = Thread.currentThread();
272
273
// Test uncontested case
274
LockAThread t1;
275
LockBThread t2;
276
277
Phaser p = new Phaser(3);
278
synchronized(objC) {
279
// Make sure the main thread is not holding any lock
280
assertNoLock(mainThread);
281
282
// Test deadlock case
283
// t1 holds lockA and attempts to lock B
284
// t2 holds lockB and attempts to lock C
285
286
t1 = new LockAThread(p);
287
t1.start();
288
289
t2 = new LockBThread(p);
290
t2.start();
291
292
p.arriveAndAwaitAdvance(); // Phase 1 (blocking)
293
checkBlockedObject(t2, objC, mainThread, Thread.State.BLOCKED);
294
checkBlockedObject(t1, objB, t2, Thread.State.BLOCKED);
295
296
long[] expectedThreads = new long[3];
297
expectedThreads[0] = t1.getId(); // blocked on lockB
298
expectedThreads[1] = t2.getId(); // owner of lockB blocking on lockC
299
expectedThreads[2] = mainThread.getId(); // owner of lockC
300
findThreadsBlockedOn(objB, expectedThreads);
301
}
302
p.arriveAndAwaitAdvance(); // Phase 2 (blocking)
303
304
p = new Phaser(2);
305
// Test Object.wait() case
306
waiter = new WaitingThread(p);
307
waiter.start();
308
309
checker = new CheckerThread();
310
checker.start();
311
312
try {
313
waiter.join();
314
checker.join();
315
} catch (InterruptedException e) {
316
e.printStackTrace();
317
testFailed = true;
318
}
319
320
if (testFailed) {
321
throw new RuntimeException("TEST FAILED.");
322
}
323
System.out.println("Test passed.");
324
}
325
326
private static ThreadInfo findOwnerInfo(ThreadInfo[] infos, String lock)
327
throws Exception {
328
ThreadInfo ownerInfo = null;
329
for (ThreadInfo info : infos) {
330
String blockedLock = info.getLockName();
331
if (lock.equals(blockedLock)) {
332
long threadId = info.getLockOwnerId();
333
if (threadId == -1) {
334
throw new RuntimeException("TEST FAILED: " +
335
lock + " expected to have owner");
336
}
337
for (int j = 0; j < infos.length; j++) {
338
if (infos[j].getThreadId() == threadId) {
339
ownerInfo = infos[j];
340
break;
341
}
342
}
343
}
344
}
345
return ownerInfo;
346
}
347
private static void findThreadsBlockedOn(Object o, long[] expectedThreads)
348
throws Exception {
349
String lock = getLockName(o);
350
// Check with ThreadInfo with no stack trace (i.e. no safepoint)
351
ThreadInfo[] infos = tm.getThreadInfo(tm.getAllThreadIds());
352
doCheck(infos, lock, expectedThreads);
353
354
// Check with ThreadInfo with stack trace
355
infos = tm.getThreadInfo(tm.getAllThreadIds(), 1);
356
doCheck(infos, lock, expectedThreads);
357
}
358
359
private static void doCheck(ThreadInfo[] infos, String lock, long[] expectedThreads)
360
throws Exception {
361
ThreadInfo ownerInfo = null;
362
// Find the thread who is blocking on lock
363
for (ThreadInfo info : infos) {
364
String blockedLock = info.getLockName();
365
if (lock.equals(blockedLock)) {
366
log("%s blocked on %s", info.getThreadName(), blockedLock);
367
ownerInfo = info;
368
}
369
}
370
if (ownerInfo == null) {
371
throw new RuntimeException("TEST FAILED: " +
372
"Can't retrieve ThreadInfo for the blocked thread");
373
}
374
375
long[] threads = new long[10];
376
int count = 0;
377
threads[count++] = ownerInfo.getThreadId();
378
while (ownerInfo != null && ownerInfo.getThreadState() == Thread.State.BLOCKED) {
379
ownerInfo = findOwnerInfo(infos, lock);
380
threads[count++] = ownerInfo.getThreadId();
381
log(" Owner = %s id = %d",
382
ownerInfo.getThreadName(),
383
ownerInfo.getThreadId()
384
);
385
lock = ownerInfo.getLockName();
386
log("%s Id = %d blocked on %s",
387
ownerInfo.getThreadName(),
388
ownerInfo.getThreadId(),
389
lock
390
);
391
}
392
log("");
393
394
if (count != expectedThreads.length) {
395
throw new RuntimeException("TEST FAILED: " +
396
"Expected chain of threads not matched; current count =" + count);
397
}
398
for (int i = 0; i < count; i++) {
399
if (threads[i] != expectedThreads[i]) {
400
log("TEST FAILED: Unexpected thread in the chain %s expected to be %s",
401
threads[i],
402
expectedThreads[i]
403
);
404
}
405
}
406
}
407
408
private static void log(String format, Object ... args) {
409
logger.log(format + "%n", args);
410
}
411
}
412
413