Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/MonitorEventsDebuggee.java
41162 views
1
/*
2
* Copyright (c) 2006, 2018, 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
package nsk.share.jdi;
24
25
import java.util.*;
26
import nsk.share.TestBug;
27
import nsk.share.locks.MonitorLockingThread;
28
29
/*
30
* This class generates MonitorWaitEvent and MonitorWaitedEvent
31
*/
32
class MonitorWaitExecutor extends EventActionsExecutor {
33
// MonitorWaited event may occurs when waiting thread was interrupted,
34
// notified by notify or notifyAll, or when timeout expired
35
enum ExitFromWaitType {
36
EXIT_WITH_TIMEOUT,
37
INTERRUPT,
38
NOTIFY,
39
NOTIFY_ALL
40
}
41
42
// this thread forces MonitorWaitExecutor to exit from wait()
43
class AuxiliaryThread extends Thread {
44
private Thread threadToInterrupt;
45
46
private Object monitor;
47
48
public AuxiliaryThread(Thread threadToInterrupt, Object monitor) {
49
this.threadToInterrupt = threadToInterrupt;
50
this.monitor = monitor;
51
}
52
53
public void run() {
54
// wait when interrupted thread switches state to 'TIMED_WAITING'
55
while ((threadToInterrupt.getState() != Thread.State.WAITING) && !exitedFromWait) {
56
Thread.yield();
57
}
58
59
// threadToInterrupt 'spuriously' exited from wait()
60
if(exitedFromWait)
61
return;
62
63
if (exitFromWaitType == ExitFromWaitType.INTERRUPT) {
64
threadToInterrupt.interrupt();
65
} else if ((exitFromWaitType == ExitFromWaitType.NOTIFY)
66
|| (exitFromWaitType == ExitFromWaitType.NOTIFY_ALL)) {
67
/*
68
* NOTE: thread's state WAITING doesn't guarantee that thread released
69
* monitor, and entering to the next synchronized block may cause MonitorContentedEnterEvent
70
* (if corresponding request was created).
71
*
72
* Debugger should take in account this issue.
73
*/
74
synchronized (monitor) {
75
if (exitFromWaitType == ExitFromWaitType.NOTIFY)
76
monitor.notify();
77
else if (exitFromWaitType == ExitFromWaitType.NOTIFY_ALL)
78
monitor.notifyAll();
79
}
80
}
81
}
82
}
83
84
// thread may 'spuriously' exit from wait(), in this case AuxiliaryThread shouldn't wait 'WAITING' state
85
private volatile boolean exitedFromWait;
86
87
// save data about MonitorWait events
88
private boolean monitorWait;
89
90
// save data about MonitorWaited events
91
private boolean monitorWaited;
92
93
public MonitorWaitExecutor(boolean monitorWait, boolean monitorWaited) {
94
this.monitorWait = monitorWait;
95
this.monitorWaited = monitorWaited;
96
}
97
98
protected ExitFromWaitType exitFromWaitType;
99
100
public void doEventAction() {
101
for (ExitFromWaitType exitType : ExitFromWaitType.values()) {
102
exitFromWaitType = exitType;
103
104
monitorWait();
105
}
106
}
107
108
protected void monitorWait() {
109
110
exitedFromWait = false;
111
112
long timeout;
113
114
if (exitFromWaitType == ExitFromWaitType.EXIT_WITH_TIMEOUT)
115
timeout = 100;
116
else
117
timeout = 0;
118
119
if (monitorWait) {
120
DebuggeeEventData.DebugMonitorWaitEventData eventData = new DebuggeeEventData.DebugMonitorWaitEventData(
121
this, Thread.currentThread(), timeout, this);
122
addEventData(eventData);
123
}
124
125
if (monitorWaited) {
126
DebuggeeEventData.DebugMonitorWaitedEventData eventData = new DebuggeeEventData.DebugMonitorWaitedEventData(
127
this, Thread.currentThread(),
128
(exitFromWaitType == ExitFromWaitType.EXIT_WITH_TIMEOUT),
129
this);
130
addEventData(eventData);
131
}
132
133
AuxiliaryThread auxiliaryThread = null;
134
135
if (exitFromWaitType != ExitFromWaitType.EXIT_WITH_TIMEOUT) {
136
auxiliaryThread = new AuxiliaryThread(Thread.currentThread(), this);
137
auxiliaryThread.start();
138
}
139
140
try {
141
eventMethod(timeout);
142
} catch (InterruptedException e) {
143
// expected exception
144
}
145
146
exitedFromWait = true;
147
148
if (auxiliaryThread != null) {
149
// don't using join, because of join is realized with using of
150
// wait(), and this method can generate unexpected events
151
while (auxiliaryThread.getState() != Thread.State.TERMINATED)
152
Thread.yield();
153
}
154
}
155
156
// move event actions to the separate method to simplify method redifinition
157
// in subclasses
158
synchronized protected void eventMethod(long timeout)
159
throws InterruptedException {
160
wait(timeout);
161
}
162
163
}
164
165
/*
166
* Subclass of MonitorWaitExecutor, define its own event method(copy of parent
167
* method), intended for event filters test
168
*/
169
class MonitorWaitExecutor_1Subclass extends MonitorWaitExecutor {
170
public MonitorWaitExecutor_1Subclass(boolean monitorWait,
171
boolean monitorWaited) {
172
super(monitorWait, monitorWaited);
173
}
174
175
synchronized protected void eventMethod(long timeout)
176
throws InterruptedException {
177
wait(timeout);
178
}
179
}
180
181
/*
182
* Subclass of MonitorWaitExecutor, define its own event method(copy of parent
183
* method), intended for event filters test
184
*/
185
class MonitorWaitExecutor_2Subclass extends MonitorWaitExecutor_1Subclass {
186
public MonitorWaitExecutor_2Subclass(boolean monitorWait,
187
boolean monitorWaited) {
188
super(monitorWait, monitorWaited);
189
}
190
191
synchronized protected void eventMethod(long timeout)
192
throws InterruptedException {
193
wait(timeout);
194
}
195
}
196
197
/*
198
* This class generates MonitorContendedEnterEvent and
199
* MonitorContendedEnteredEvent
200
*/
201
class MonitorEnterExecutor extends EventActionsExecutor {
202
/*
203
* Types of monitor acquiring:
204
* - through synchronized block
205
* - through synchronized method
206
* - through JNI MonitorEnter
207
*/
208
static enum MonitorAcquireType {
209
SYNCHRONIZED_BLOCK,
210
SYNCHRONIZED_METHOD,
211
JNI_MONITOR_ENTER
212
}
213
214
// native method uses this class
215
private static final Class<?> jniError = nsk.share.TestJNIError.class;
216
217
218
static final String nativeLibararyName = "MonitorEnterExecutor";
219
220
static {
221
System.loadLibrary(nativeLibararyName);
222
}
223
224
// this thread forces MonitorLockingThread to release holding lock
225
static class LockFreeThread extends Thread {
226
private Thread blockedThread;
227
228
private MonitorLockingThread lockingThread;
229
230
public LockFreeThread(Thread blockedThread,
231
MonitorLockingThread lockingThread) {
232
this.blockedThread = blockedThread;
233
this.lockingThread = lockingThread;
234
}
235
236
public void run() {
237
// wait when blocked thread switches state to 'BLOCKED'
238
while (blockedThread.getState() != Thread.State.BLOCKED)
239
Thread.yield();
240
241
lockingThread.releaseLock();
242
}
243
}
244
245
private boolean monitorEnter;
246
247
private boolean monitorEntered;
248
249
public MonitorEnterExecutor(boolean monitorEnter, boolean monitorEntered) {
250
this.monitorEnter = monitorEnter;
251
this.monitorEntered = monitorEntered;
252
}
253
254
protected void monitorEnter() {
255
// locking thread acquires 'this' lock
256
MonitorLockingThread lockingThread = new MonitorLockingThread(this);
257
lockingThread.acquireLock();
258
259
if (monitorEnter) {
260
DebuggeeEventData.DebugMonitorEnterEventData eventData = new DebuggeeEventData.DebugMonitorEnterEventData(
261
this, Thread.currentThread(), this);
262
addEventData(eventData);
263
}
264
if (monitorEntered) {
265
DebuggeeEventData.DebugMonitorEnteredEventData eventData = new DebuggeeEventData.DebugMonitorEnteredEventData(
266
this, Thread.currentThread(), this);
267
addEventData(eventData);
268
}
269
270
/*
271
* This thread forces lockingThread to free 'this' lock when current thread's state will change to 'BLOCKED'
272
*
273
* NOTE: this method to provoke MonitorContended events isn't 100% robust
274
* Tests should take in account this issue.
275
*
276
*/
277
LockFreeThread lockFreeThread = new LockFreeThread(Thread.currentThread(), lockingThread);
278
lockFreeThread.start();
279
280
// try to acquire 'this' lock
281
eventMethod();
282
283
while(lockingThread.getState() != Thread.State.TERMINATED)
284
Thread.yield();
285
286
while(lockFreeThread.getState() != Thread.State.TERMINATED)
287
Thread.yield();
288
}
289
290
private MonitorAcquireType monitorAcquireType;
291
292
// generate events in different ways
293
public void doEventAction() {
294
for (MonitorAcquireType monitorAcquireType : MonitorAcquireType.values()) {
295
this.monitorAcquireType = monitorAcquireType;
296
monitorEnter();
297
}
298
}
299
300
protected void eventMethod() {
301
switch (monitorAcquireType) {
302
case SYNCHRONIZED_BLOCK:
303
synchronizedBlock();
304
break;
305
case SYNCHRONIZED_METHOD:
306
synchronizedMethod();
307
break;
308
case JNI_MONITOR_ENTER:
309
nativeJNIMonitorEnter();
310
break;
311
312
default:
313
throw new TestBug("Invalid monitorAcquireType: "
314
+ monitorAcquireType);
315
}
316
}
317
318
// move event actions to the separate methods to simplify method
319
// redifinition in subclasses:
320
321
protected void synchronizedBlock() {
322
// MonitorContendedEnterEvent and MonitorContendedEnteredEvent should occur here
323
synchronized (this) {
324
// don't expect events for following synchronized block
325
synchronized (this) {
326
}
327
}
328
}
329
330
// MonitorContendedEnterEvent and MonitorContendedEnteredEvent should occur here
331
synchronized protected void synchronizedMethod() {
332
// don't expect events for following synchronized block
333
synchronized (this) {
334
}
335
}
336
337
// call JNI methods MonitorEnter and MonitorExit for 'this' object
338
protected native void nativeJNIMonitorEnter();
339
340
}
341
342
/*
343
* Subclass of MonitorEnterExecutor, defines its own event methods(copy of parent
344
* method), intended for event filters test
345
*/
346
class MonitorEnterExecutor_1Subclass extends MonitorEnterExecutor {
347
static {
348
System.loadLibrary(nativeLibararyName);
349
}
350
351
public MonitorEnterExecutor_1Subclass(boolean monitorEnter,
352
boolean monitorEntered) {
353
super(monitorEnter, monitorEntered);
354
}
355
356
protected void synchronizedBlock() {
357
// MonitorContendedEnterEvent and MonitorContendedEnteredEvent should occur here
358
synchronized (this) {
359
}
360
}
361
362
// MonitorContendedEnterEvent and MonitorContendedEnteredEvent should occur here
363
synchronized protected void synchronizedMethod() {
364
}
365
366
// call JNI methods MonitorEnter and MonitorExit for 'this' object
367
protected native void nativeJNIMonitorEnter();
368
}
369
370
/*
371
* Subclass of MonitorEnterExecutor, defines its own event methods(copy of parent
372
* method), intended for event filters test
373
*/
374
class MonitorEnterExecutor_2Subclass extends MonitorEnterExecutor_1Subclass {
375
static {
376
System.loadLibrary(nativeLibararyName);
377
}
378
379
public MonitorEnterExecutor_2Subclass(boolean monitorEnter,
380
boolean monitorEntered) {
381
super(monitorEnter, monitorEntered);
382
}
383
384
protected void synchronizedBlock() {
385
// MonitorContendedEnterEvent and MonitorContendedEnteredEvent should occur here
386
synchronized (this) {
387
}
388
}
389
390
// MonitorContendedEnterEvent and MonitorContendedEnteredEvent should occur here
391
synchronized protected void synchronizedMethod() {
392
}
393
394
// call JNI methods MonitorEnter and MonitorExit for 'this' object
395
protected native void nativeJNIMonitorEnter();
396
}
397
398
/*
399
* Class is used as base debuggee in tests for following events and event requests:
400
* - MonitorContendedEnterRequest / MonitorContendedEnterEvent
401
* - MonitorContendedEnteredRequest / MonitorContendedEnteredEvent
402
* - MonitorWaitRequest / MonitorWaitEvent
403
* - MonitorWaitedRequest / MonitorWaitedEvent
404
*/
405
public class MonitorEventsDebuggee extends JDIEventsDebuggee {
406
public static void main(String[] args) {
407
MonitorEventsDebuggee debuggee = new MonitorEventsDebuggee();
408
debuggee.doTest(args);
409
}
410
411
protected void createActionsExecutors(String description, int eventsCount) {
412
boolean monitorEnter = description
413
.contains(JDIEventsDebugger.EventType.MONITOR_CONTENTED_ENTER
414
.name());
415
boolean monitorEntered = description
416
.contains(JDIEventsDebugger.EventType.MONITOR_CONTENTED_ENTERED
417
.name());
418
boolean monitorWait = description
419
.contains(JDIEventsDebugger.EventType.MONITOR_WAIT.name());
420
boolean monitorWaited = description
421
.contains(JDIEventsDebugger.EventType.MONITOR_WAITED.name());
422
423
if (monitorEnter || monitorEntered || monitorWait || monitorWaited) {
424
createActionsExecutors(monitorEnter, monitorEntered, monitorWait,
425
monitorWaited, eventsCount);
426
} else
427
throw new TestBug(
428
"Invalid command format (required event not specified)");
429
}
430
431
private List<DebuggeeEventData.DebugMonitorEventData> eventsData = new ArrayList<DebuggeeEventData.DebugMonitorEventData>();
432
433
protected void clearResults() {
434
super.clearResults();
435
eventsData.clear();
436
}
437
438
private void createActionsExecutors(boolean monitorEnter,
439
boolean monitorEntered, boolean monitorWait, boolean monitorWaited,
440
int actionsCount) {
441
EventActionsThread thread;
442
443
// create 3 instances of generating objects of 3 different classes (for
444
// event filters tests)
445
if (monitorEnter || monitorEntered) {
446
thread = new EventActionsThread(new MonitorEnterExecutor(
447
monitorEnter, monitorEntered), actionsCount);
448
thread.start();
449
eventActionsExecutorsPool.add(thread);
450
451
thread = new EventActionsThread(new MonitorEnterExecutor_1Subclass(
452
monitorEnter, monitorEntered), actionsCount);
453
thread.start();
454
eventActionsExecutorsPool.add(thread);
455
456
thread = new EventActionsThread(new MonitorEnterExecutor_2Subclass(
457
monitorEnter, monitorEntered), actionsCount);
458
thread.start();
459
eventActionsExecutorsPool.add(thread);
460
}
461
462
// create 3 instances of generating objects of 3 different classes (for
463
// event filters tests)
464
if (monitorWait || monitorWaited) {
465
thread = new EventActionsThread(new MonitorWaitExecutor(
466
monitorWait, monitorWaited), actionsCount);
467
thread.start();
468
eventActionsExecutorsPool.add(thread);
469
470
thread = new EventActionsThread(new MonitorWaitExecutor_1Subclass(
471
monitorWait, monitorWaited), actionsCount);
472
thread.start();
473
eventActionsExecutorsPool.add(thread);
474
475
thread = new EventActionsThread(new MonitorWaitExecutor_2Subclass(
476
monitorWait, monitorWaited), actionsCount);
477
thread.start();
478
eventActionsExecutorsPool.add(thread);
479
}
480
}
481
482
// start event generating threads and wait when all this threads finish
483
// execution
484
// override parent method because of Thread.join() used in parent method
485
// generates unexpected MonitorWait/MonitorWaited events
486
protected void startExecution() {
487
if (eventActionsExecutorsPool.size() == 0) {
488
throw new TestBug("ActionsExecutors were not created");
489
}
490
491
for (EventActionsThread thread : eventActionsExecutorsPool) {
492
thread.startExecution();
493
}
494
495
// wait completion of test threads in separate thread to free thread listening commands
496
executionControllingThread = new Thread(
497
new Runnable() {
498
public void run() {
499
boolean executionCompleted;
500
do {
501
try {
502
// give time to event generators
503
Thread.sleep(500);
504
} catch (InterruptedException e) {
505
unexpectedException(e);
506
}
507
executionCompleted = true;
508
for (EventActionsThread thread : eventActionsExecutorsPool) {
509
if (thread.isAlive()) {
510
executionCompleted = false;
511
break;
512
}
513
}
514
} while (!executionCompleted);
515
516
completeExecution();
517
}
518
});
519
520
executionControllingThread.start();
521
}
522
523
}
524
525