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/SynchronizationStatistics.java
38821 views
1
/*
2
* Copyright (c) 2003, 2015, 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 the synchronization statistics support:
28
*
29
* @author Mandy Chung
30
* @author Jaroslav Bachorik
31
*
32
* @run main/othervm SynchronizationStatistics
33
*/
34
35
import java.lang.management.*;
36
import java.util.concurrent.Phaser;
37
import java.util.function.Supplier;
38
39
public class SynchronizationStatistics {
40
private static class LockerThread extends Thread {
41
public LockerThread(Runnable r) {
42
super(r, "LockerThread");
43
}
44
}
45
46
private static final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
47
48
private static final boolean blockedTimeCheck =
49
mbean.isThreadContentionMonitoringSupported();
50
51
52
public static void main(String args[]) throws Exception {
53
if (blockedTimeCheck) {
54
mbean.setThreadContentionMonitoringEnabled(true);
55
}
56
57
if (!mbean.isThreadContentionMonitoringEnabled()) {
58
throw new RuntimeException("TEST FAILED: " +
59
"Thread Contention Monitoring is not enabled");
60
}
61
62
testBlockingOnSimpleMonitor();
63
testBlockingOnNestedMonitor();
64
testWaitingOnSimpleMonitor();
65
testMultiWaitingOnSimpleMonitor();
66
testWaitingOnNestedMonitor();
67
68
System.out.println("Test passed.");
69
}
70
71
private static LockerThread newLockerThread(Runnable r) {
72
LockerThread t = new LockerThread(r);
73
t.setDaemon(true);
74
return t;
75
}
76
77
private static void waitForThreadState(Thread t, Thread.State state) throws InterruptedException {
78
while (t.getState() != state) {
79
Thread.sleep(3);
80
}
81
}
82
83
/**
84
* Tests that blocking on a single monitor properly increases the
85
* blocked count at least by 1. Also asserts that the correct lock name is provided.
86
*/
87
private static void testBlockingOnSimpleMonitor() throws Exception {
88
System.out.println("testBlockingOnSimpleMonitor");
89
final Object lock1 = new Object();
90
System.out.println("Lock1 = " + lock1);
91
92
final Phaser p = new Phaser(2);
93
LockerThread lt = newLockerThread(new Runnable() {
94
@Override
95
public void run() {
96
p.arriveAndAwaitAdvance(); // phase[1]
97
synchronized(lock1) {
98
System.out.println("[LockerThread obtained Lock1]");
99
p.arriveAndAwaitAdvance(); // phase[2]
100
}
101
p.arriveAndAwaitAdvance(); // phase[3]
102
}
103
});
104
105
lt.start();
106
long tid = lt.getId();
107
ThreadInfo ti = mbean.getThreadInfo(tid);
108
String lockName = null;
109
synchronized(lock1) {
110
p.arriveAndAwaitAdvance(); // phase[1]
111
waitForThreadState(lt, Thread.State.BLOCKED);
112
do {
113
lockName = mbean.getThreadInfo(tid).getLockName();
114
} while (lockName == null);
115
}
116
117
p.arriveAndAwaitAdvance(); // phase[2]
118
testBlocked(ti, () -> mbean.getThreadInfo(tid), lockName, lock1);
119
p.arriveAndDeregister(); // phase[3]
120
121
lt.join();
122
123
printok();
124
}
125
126
/**
127
* Tests that blocking on a nested monitor properly increases the
128
* blocked count at least by 1 - it is not affected by the nesting depth.
129
* Also asserts that the correct lock name is provided.
130
*/
131
private static void testBlockingOnNestedMonitor() throws Exception {
132
System.out.println("testBlockingOnNestedMonitor");
133
final Object lock1 = new Object();
134
final Object lock2 = new Object();
135
136
System.out.println("Lock1 = " + lock1);
137
System.out.println("Lock2 = " + lock2);
138
139
final Phaser p = new Phaser(2);
140
LockerThread lt = newLockerThread(new Runnable() {
141
@Override
142
public void run() {
143
p.arriveAndAwaitAdvance(); // phase[1]
144
synchronized(lock1) {
145
System.out.println("[LockerThread obtained Lock1]");
146
p.arriveAndAwaitAdvance(); // phase[2]
147
p.arriveAndAwaitAdvance(); // phase[3]
148
synchronized(lock2) {
149
System.out.println("[LockerThread obtained Lock2]");
150
p.arriveAndAwaitAdvance(); // phase[4]
151
}
152
p.arriveAndAwaitAdvance(); // phase[5]
153
}
154
}
155
});
156
157
lt.start();
158
long tid = lt.getId();
159
ThreadInfo ti = mbean.getThreadInfo(tid);
160
String lockName = null;
161
synchronized(lock1) {
162
p.arriveAndAwaitAdvance(); // phase[1]
163
waitForThreadState(lt, Thread.State.BLOCKED);
164
do {
165
lockName = mbean.getThreadInfo(tid).getLockName();
166
} while (lockName == null);
167
}
168
p.arriveAndAwaitAdvance(); // phase[2]
169
170
ti = testBlocked(ti, () -> mbean.getThreadInfo(tid), lockName, lock1);
171
172
synchronized(lock2) {
173
p.arriveAndAwaitAdvance(); // phase [3]
174
waitForThreadState(lt, Thread.State.BLOCKED);
175
do {
176
lockName = mbean.getThreadInfo(tid).getLockName();
177
} while (lockName == null);
178
}
179
p.arriveAndAwaitAdvance(); // phase [4]
180
testBlocked(ti, () -> mbean.getThreadInfo(tid), lockName, lock2);
181
p.arriveAndDeregister();
182
183
lt.join();
184
185
printok();
186
}
187
188
/**
189
* Tests that waiting on a single monitor properly increases the waited
190
* count by 1 and the waited time by a positive number.
191
*/
192
private static void testWaitingOnSimpleMonitor() throws Exception {
193
System.out.println("testWaitingOnSimpleMonitor");
194
final Object lock1 = new Object();
195
final Phaser p = new Phaser(2);
196
LockerThread lt = newLockerThread(new Runnable() {
197
@Override
198
public void run() {
199
p.arriveAndAwaitAdvance(); // phase[1]
200
synchronized(lock1) {
201
System.out.println("[LockerThread obtained Lock1]");
202
try {
203
lock1.wait(300);
204
} catch (InterruptedException ex) {
205
// ignore
206
}
207
p.arriveAndAwaitAdvance(); // phase[2]
208
}
209
p.arriveAndAwaitAdvance(); // phase[3]
210
}
211
});
212
213
lt.start();
214
ThreadInfo ti1 = mbean.getThreadInfo(lt.getId());
215
synchronized(lock1) {
216
p.arriveAndAwaitAdvance(); // phase[1]
217
waitForThreadState(lt, Thread.State.BLOCKED);
218
}
219
p.arriveAndAwaitAdvance(); // phase[2]
220
221
testWaited(ti1, () -> mbean.getThreadInfo(lt.getId()), 1);
222
p.arriveAndDeregister(); // phase[3]
223
224
lt.join();
225
226
printok();
227
}
228
229
/**
230
* Tests that waiting multiple times on the same monitor subsequently
231
* increases the waited count by the number of subsequent calls and the
232
* waited time by a positive number.
233
*/
234
private static void testMultiWaitingOnSimpleMonitor() throws Exception {
235
System.out.println("testWaitingOnMultipleMonitors");
236
final Object lock1 = new Object();
237
238
final Phaser p = new Phaser(2);
239
LockerThread lt = newLockerThread(new Runnable() {
240
@Override
241
public void run() {
242
p.arriveAndAwaitAdvance(); // phase[1]
243
synchronized(lock1) {
244
System.out.println("[LockerThread obtained Lock1]");
245
for (int i = 0; i < 3; i++) {
246
try {
247
lock1.wait(300);
248
} catch (InterruptedException ex) {
249
// ignore
250
}
251
p.arriveAndAwaitAdvance(); // phase[2-4]
252
}
253
}
254
p.arriveAndAwaitAdvance(); // phase[5]
255
}
256
});
257
258
lt.start();
259
ThreadInfo ti1 = mbean.getThreadInfo(lt.getId());
260
synchronized(lock1) {
261
p.arriveAndAwaitAdvance(); //phase[1]
262
waitForThreadState(lt, Thread.State.BLOCKED);
263
}
264
int phase = p.getPhase();
265
while ((p.arriveAndAwaitAdvance() - phase) < 3); // phase[2-4]
266
267
testWaited(ti1, () -> mbean.getThreadInfo(lt.getId()), 3);
268
p.arriveAndDeregister(); // phase[5]
269
270
lt.join();
271
272
printok();
273
}
274
275
/**
276
* Tests that waiting on monitors places in nested synchronized blocks
277
* properly increases the waited count by the number of times the "lock.wait()"
278
* was invoked and the waited time by a positive number.
279
*/
280
private static void testWaitingOnNestedMonitor() throws Exception {
281
System.out.println("testWaitingOnNestedMonitor");
282
final Object lock1 = new Object();
283
final Object lock2 = new Object();
284
final Object lock3 = new Object();
285
286
final Phaser p = new Phaser(2);
287
LockerThread lt = newLockerThread(new Runnable() {
288
@Override
289
public void run() {
290
p.arriveAndAwaitAdvance(); // phase[1]
291
synchronized(lock1) {
292
System.out.println("[LockerThread obtained Lock1]");
293
try {
294
lock1.wait(300);
295
} catch (InterruptedException ex) {
296
// ignore
297
}
298
299
p.arriveAndAwaitAdvance(); // phase[2]
300
synchronized(lock2) {
301
System.out.println("[LockerThread obtained Lock2]");
302
try {
303
lock2.wait(300);
304
} catch (InterruptedException ex) {
305
// ignore
306
}
307
308
p.arriveAndAwaitAdvance(); // phase[3]
309
synchronized(lock3) {
310
System.out.println("[LockerThread obtained Lock3]");
311
try {
312
lock3.wait(300);
313
} catch (InterruptedException ex) {
314
// ignore
315
}
316
p.arriveAndAwaitAdvance(); // phase[4]
317
}
318
}
319
}
320
p.arriveAndAwaitAdvance(); // phase[5]
321
}
322
});
323
324
lt.start();
325
ThreadInfo ti1 = mbean.getThreadInfo(lt.getId());
326
synchronized(lock1) {
327
p.arriveAndAwaitAdvance(); // phase[1]
328
waitForThreadState(lt, Thread.State.BLOCKED);
329
}
330
331
synchronized(lock2) {
332
p.arriveAndAwaitAdvance(); // phase[2]
333
waitForThreadState(lt, Thread.State.BLOCKED);
334
}
335
336
synchronized(lock3) {
337
p.arriveAndAwaitAdvance(); // phase[3]
338
waitForThreadState(lt, Thread.State.BLOCKED);
339
}
340
341
p.arriveAndAwaitAdvance(); // phase[4]
342
testWaited(ti1, () -> mbean.getThreadInfo(lt.getId()), 3);
343
p.arriveAndDeregister(); // phase[5]
344
345
lt.join();
346
printok();
347
}
348
349
private static void printok() {
350
System.out.println("OK\n");
351
}
352
353
private static void testWaited(ThreadInfo ti1, Supplier<ThreadInfo> ti2, int waited)
354
throws InterruptedException {
355
boolean error;
356
do {
357
error = false;
358
ThreadInfo ti = ti2.get();
359
long waitCntDiff = ti.getWaitedCount() - ti1.getWaitedCount();
360
long waitTimeDiff = ti.getWaitedTime() - ti1.getWaitedTime();
361
if (waitCntDiff < waited) {
362
System.err.println(
363
"Unexpected diff in waited count. Expecting at least "
364
+ waited + " , got " + waitCntDiff
365
);
366
error = true;
367
}
368
if (waitTimeDiff <= 0) {
369
System.err.println(
370
"Unexpected diff in waited time. Expecting increasing " +
371
"value, got " + waitTimeDiff + "ms"
372
);
373
error = true;
374
}
375
if (error) {
376
System.err.println("Retrying in 20ms ...");
377
Thread.sleep(20);
378
}
379
} while (error);
380
}
381
382
private static ThreadInfo testBlocked(ThreadInfo ti1, Supplier<ThreadInfo> ti2,
383
String lockName, final Object lock)
384
throws InterruptedException {
385
boolean error;
386
ThreadInfo ti = null;
387
do {
388
error = false;
389
ti = ti2.get();
390
long blkCntDiff = ti.getBlockedCount() - ti1.getBlockedCount();
391
long blkTimeDiff = ti.getBlockedTime() - ti1.getBlockedTime();
392
393
System.out.println("testBlocked: [" + blkCntDiff + ", " + blkTimeDiff + ", " + lockName + "]");
394
395
if (blkCntDiff < 1) {
396
System.err.println(
397
"Unexpected diff in blocked count. Expecting at least 1, " +
398
"got " + blkCntDiff
399
);
400
error = true;
401
}
402
if (blkTimeDiff < 0) {
403
System.err.println(
404
"Unexpected diff in blocked time. Expecting a positive " +
405
"number, got " + blkTimeDiff
406
);
407
error = true;
408
}
409
if (!lockName.equals(lock.toString())) {
410
System.err.println(
411
"Unexpected blocked monitor name. Expecting " +
412
lock.toString() + ", got " + lockName
413
);
414
error = true;
415
}
416
if (error) {
417
System.err.println("Retrying in 20ms ...");
418
Thread.sleep(20);
419
}
420
} while (error);
421
return ti;
422
}
423
}
424
425