• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package art;
18 
19 import java.util.concurrent.Semaphore;
20 
21 public class Test1932 {
22   public static final boolean PRINT_FULL_STACK_TRACE = false;
23   public static final boolean INCLUDE_ANDROID_ONLY_TESTS = false;
24 
25   public static interface MonitorHandler {
handleMonitorEnter(Thread thd, Object lock)26     public default void handleMonitorEnter(Thread thd, Object lock) {}
handleMonitorEntered(Thread thd, Object lock)27     public default void handleMonitorEntered(Thread thd, Object lock) {}
handleMonitorWait(Thread thd, Object lock, long timeout)28     public default void handleMonitorWait(Thread thd, Object lock, long timeout) {}
handleMonitorWaited(Thread thd, Object lock, boolean timed_out)29     public default void handleMonitorWaited(Thread thd, Object lock, boolean timed_out) {}
30   }
31 
32   public static volatile MonitorHandler HANDLER = null;
33 
run()34   public static void run() throws Exception {
35     Monitors.setupMonitorEvents(
36         Test1932.class,
37         Test1932.class.getDeclaredMethod("handleMonitorEnter", Thread.class, Object.class),
38         Test1932.class.getDeclaredMethod("handleMonitorEntered", Thread.class, Object.class),
39         Test1932.class.getDeclaredMethod("handleMonitorWait",
40           Thread.class, Object.class, Long.TYPE),
41         Test1932.class.getDeclaredMethod("handleMonitorWaited",
42           Thread.class, Object.class, Boolean.TYPE),
43         Monitors.NamedLock.class,
44         null);
45 
46     System.out.println("Testing contended locking where lock is released before callback ends.");
47     testLockUncontend(new Monitors.NamedLock("Lock testLockUncontend"));
48 
49     System.out.println("Testing throwing exceptions in monitor_enter");
50     testLockThrowEnter(new Monitors.NamedLock("Lock testLockThrowEnter"));
51 
52     System.out.println("Testing throwing exceptions in monitor_entered");
53     testLockThrowEntered(new Monitors.NamedLock("Lock testLockThrowEntered"));
54 
55     System.out.println("Testing throwing exceptions in both monitorEnter & MonitorEntered");
56     testLockThrowBoth(new Monitors.NamedLock("Lock testLockThrowBoth"));
57 
58     // This exposes a difference between the RI and ART. On the RI this test will cause a
59     // JVMTI_EVENT_MONITOR_WAITED event to be sent even though we threw an exception during the
60     // JVMTI_EVENT_MONITOR_WAIT. See b/65558434.
61     System.out.println("Testing throwing exception in MonitorWait event");
62     testThrowWait(new Monitors.NamedLock("Lock testThrowWait"));
63 
64     System.out.println("Testing throwing exception in MonitorWait event with illegal aruments");
65     testThrowIllegalWait(new Monitors.NamedLock("Lock testThrowIllegalWait"));
66 
67     System.out.println("Testing throwing exception in MonitorWaited event");
68     testThrowWaited(new Monitors.NamedLock("Lock testThrowWaited"));
69 
70     System.out.println("Testing throwing exception in MonitorWaited event caused by timeout");
71     testThrowWaitedTimeout(new Monitors.NamedLock("Lock testThrowWaitedTimeout"));
72 
73     System.out.println("Testing throwing exception in MonitorWaited event caused by interrupt");
74     testThrowWaitedInterrupt(new Monitors.NamedLock("Lock testThrowWaitedInterrupt"));
75 
76     System.out.println("Testing ObjectMonitorInfo inside of events");
77     testMonitorInfoInEvents(new Monitors.NamedLock("Lock testMonitorInfoInEvents"));
78 
79     System.out.println("Testing that the monitor can be stolen during the MonitorWaited event.");
80     testWaitEnterInterleaving(new Monitors.NamedLock("test testWaitEnterInterleaving"));
81 
82     // TODO We keep this here since it works on android but it's not clear it's behavior we want to
83     // support long term or at all.
84     if (INCLUDE_ANDROID_ONLY_TESTS) {
85       System.out.println(
86           "Testing that the monitor can be still held by notifier during the MonitorWaited " +
87           "event. NB This doesn't work on the RI.");
88       testWaitExitInterleaving(new Monitors.NamedLock("test testWaitExitInterleaving"));
89     }
90 
91     System.out.println(
92         "Testing that we can lock and release the monitor in the MonitorWait event");
93     testWaitMonitorEnter(new Monitors.NamedLock("test testWaitMonitorEnter"));
94 
95     System.out.println(
96         "Testing that we can lock and release the monitor in the MonitorWaited event");
97     testWaitedMonitorEnter(new Monitors.NamedLock("test testWaitedMonitorEnter"));
98 
99     System.out.println("Testing we can perform recursive lock in MonitorEntered");
100     testRecursiveMontiorEnteredLock(new Monitors.NamedLock("test testRecursiveMontiorEnteredLock"));
101 
102     System.out.println("Testing the lock state if MonitorEnter throws in a native method");
103     testNativeLockStateThrowEnter(new Monitors.NamedLock("test testNativeLockStateThrowEnter"));
104 
105     System.out.println("Testing the lock state if MonitorEntered throws in a native method");
106     testNativeLockStateThrowEntered(new Monitors.NamedLock("test testNativeLockStateThrowEntered"));
107   }
108 
doNativeLockPrint(Monitors.NamedLock lk)109   public static native void doNativeLockPrint(Monitors.NamedLock lk);
printLockState(Monitors.NamedLock lk, Object exception, int res)110   public static void printLockState(Monitors.NamedLock lk, Object exception, int res) {
111     System.out.println(
112         "MonitorEnter returned: " + res + "\n" +
113         "Lock state is: " + Monitors.getObjectMonitorUsage(lk));
114     printExceptions((Throwable)exception);
115   }
116 
testNativeLockStateThrowEnter(final Monitors.NamedLock lk)117   public static void testNativeLockStateThrowEnter(final Monitors.NamedLock lk) throws Exception {
118     final Monitors.LockController controller1 = new Monitors.LockController(lk);
119     HANDLER = new MonitorHandler() {
120       @Override public void handleMonitorEnter(Thread t, Object l) {
121         System.out.println("Unlocking controller1 in MonitorEnter");
122         try {
123           controller1.DoUnlock();
124         } catch (Exception e) {
125           throw new Monitors.TestException("Exception unlocking monitor in MonitorEnter " + l, e);
126         }
127         System.out.println("Throwing exception in MonitorEnter");
128         throw new Monitors.TestException("throwing exception during monitorEnter of " + l);
129       }
130     };
131     controller1.DoLock();
132     controller1.waitForLockToBeHeld();
133     Thread native_thd = new Thread(() -> {
134       try {
135         doNativeLockPrint(lk);
136       } catch (Throwable e) {
137         System.out.println("Unhandled exception: " + e);
138         e.printStackTrace();
139       }
140     }, "NativeLockStateThrowEnter thread");
141     native_thd.start();
142     native_thd.join();
143   }
144 
testNativeLockStateThrowEntered(final Monitors.NamedLock lk)145   public static void testNativeLockStateThrowEntered(final Monitors.NamedLock lk) throws Exception {
146     final Monitors.LockController controller1 = new Monitors.LockController(lk);
147     HANDLER = new MonitorHandler() {
148       @Override public void handleMonitorEnter(Thread t, Object l) {
149         System.out.println("Unlocking controller1 in MonitorEnter");
150         try {
151           controller1.DoUnlock();
152         } catch (Exception e) {
153           throw new Monitors.TestException("Exception unlocking monitor in MonitorEnter " + l, e);
154         }
155       }
156       @Override public void handleMonitorEntered(Thread t, Object l) {
157         System.out.println("Throwing exception in MonitorEntered");
158         throw new Monitors.TestException("throwing exception during monitorEntered of " + l);
159       }
160     };
161     controller1.DoLock();
162     controller1.waitForLockToBeHeld();
163     Thread native_thd = new Thread(() -> {
164       try {
165         doNativeLockPrint(lk);
166       } catch (Throwable e) {
167         System.out.println("Unhandled exception: " + e);
168         e.printStackTrace();
169       }
170     }, "NativeLockStateThrowEntered thread");
171     native_thd.start();
172     native_thd.join();
173   }
174 
testRecursiveMontiorEnteredLock(final Monitors.NamedLock lk)175   public static void testRecursiveMontiorEnteredLock(final Monitors.NamedLock lk) throws Exception {
176     Monitors.LockController controller1 = new Monitors.LockController(lk);
177     Monitors.LockController controller2 = new Monitors.LockController(lk);
178     HANDLER = new MonitorHandler() {
179       @Override public void handleMonitorEntered(Thread thd, Object l) {
180         try {
181           System.out.println("In MonitorEntered usage: " + Monitors.getObjectMonitorUsage(lk));
182           synchronized (lk) {
183             System.out.println("In MonitorEntered sync: " + Monitors.getObjectMonitorUsage(lk));
184           }
185         } catch (Exception e) {
186           throw new Monitors.TestException("error while recursive locking!", e);
187         }
188       }
189     };
190     controller1.DoLock();
191     controller1.waitForLockToBeHeld();
192     controller2.DoLock();
193     controller2.waitForContendedSleep();
194     controller1.DoUnlock();
195     controller2.waitForLockToBeHeld();
196     controller2.DoUnlock();
197   }
198 
testWaitedMonitorEnter(final Monitors.NamedLock lk)199   public static void testWaitedMonitorEnter(final Monitors.NamedLock lk) throws Exception {
200     final Monitors.LockController controller1 = new Monitors.LockController(lk);
201     final Monitors.LockController controller2 = new Monitors.LockController(lk);
202     HANDLER = new MonitorHandler() {
203       @Override public void handleMonitorWaited(Thread thd, Object l, boolean timeout) {
204         try {
205           // make sure that controller2 has acutally unlocked everything, we can be sent earlier
206           // than that on ART.
207           while (controller2.IsLocked()) {}
208           System.out.println("In waited monitor usage: " + Monitors.getObjectMonitorUsage(lk));
209           synchronized (lk) {
210             System.out.println(
211                 "In waited monitor usage sync: " + Monitors.getObjectMonitorUsage(lk));
212           }
213         } catch (Exception e) {
214           throw new Monitors.TestException("error while doing unlock in other thread!", e);
215         }
216       }
217     };
218     controller1.DoLock();
219     controller1.waitForLockToBeHeld();
220     controller1.DoWait();
221     controller1.waitForNotifySleep();
222     controller2.DoLock();
223     controller2.waitForLockToBeHeld();
224     controller2.DoNotifyAll();
225     controller2.DoUnlock();
226     controller1.waitForLockToBeHeld();
227     controller1.DoUnlock();
228   }
229 
testWaitMonitorEnter(final Monitors.NamedLock lk)230   public static void testWaitMonitorEnter(final Monitors.NamedLock lk) throws Exception {
231     final Monitors.LockController controller1 = new Monitors.LockController(lk);
232     final Monitors.LockController controller2 = new Monitors.LockController(lk);
233     HANDLER = new MonitorHandler() {
234       @Override public void handleMonitorWait(Thread thd, Object l, long timeout) {
235         try {
236           System.out.println("In wait monitor usage: " + Monitors.getObjectMonitorUsage(lk));
237           synchronized (lk) {
238             System.out.println("In wait monitor usage sync: " + Monitors.getObjectMonitorUsage(lk));
239           }
240         } catch (Exception e) {
241           throw new Monitors.TestException("error while doing unlock in other thread!", e);
242         }
243       }
244     };
245     controller1.DoLock();
246     controller1.waitForLockToBeHeld();
247     controller1.DoWait();
248     controller1.waitForNotifySleep();
249     controller2.DoLock();
250     controller2.waitForLockToBeHeld();
251     controller2.DoNotifyAll();
252     controller2.DoUnlock();
253     controller1.waitForLockToBeHeld();
254     controller1.DoUnlock();
255   }
256 
257   // NB This test cannot be run on the RI. It deadlocks. Leaving for documentation.
testWaitExitInterleaving(Monitors.NamedLock lk)258   public static void testWaitExitInterleaving(Monitors.NamedLock lk) throws Exception {
259     final Monitors.LockController controller1 = new Monitors.LockController(lk);
260     final Monitors.LockController controller2 = new Monitors.LockController(lk);
261     HANDLER = new MonitorHandler() {
262       @Override public void handleMonitorWaited(Thread thd, Object l, boolean timeout) {
263         System.out.println("un-locking controller1 in controller2 MonitorWaited event");
264         try {
265           controller1.DoUnlock();
266         } catch (Exception e) {
267           throw new Monitors.TestException("error while doing unlock in other thread!", e);
268         }
269       }
270     };
271     controller2.DoLock();
272     controller2.waitForLockToBeHeld();
273     controller2.DoWait();
274     controller2.waitForNotifySleep();
275     controller1.DoLock();
276     controller1.waitForLockToBeHeld();
277     controller1.DoNotifyAll();
278     controller2.waitForLockToBeHeld();
279     controller2.DoUnlock();
280   }
281 
testWaitEnterInterleaving(Monitors.NamedLock lk)282   public static void testWaitEnterInterleaving(Monitors.NamedLock lk) throws Exception {
283     final Monitors.LockController controller1 = new Monitors.LockController(lk);
284     final Monitors.LockController controller2 = new Monitors.LockController(lk);
285     final Monitors.LockController controller3 = new Monitors.LockController(lk);
286     final Semaphore unlocked_sem = new Semaphore(0);
287     final Semaphore continue_sem = new Semaphore(0);
288     HANDLER = new MonitorHandler() {
289       @Override public void handleMonitorWaited(Thread thd, Object l, boolean timeout) {
290         System.out.println("locking controller3 in controller2 MonitorWaited event");
291         try {
292           unlocked_sem.acquire();
293           controller3.DoLock();
294           controller3.waitForLockToBeHeld();
295           System.out.println(
296               "Controller3 now holds the lock the monitor wait will try to re-acquire");
297           continue_sem.release();
298         } catch (Exception e) {
299           throw new Monitors.TestException("error while doing unlock in other thread!", e);
300         }
301       }
302     };
303     controller2.DoLock();
304     controller2.waitForLockToBeHeld();
305     controller2.DoWait();
306     controller2.waitForNotifySleep();
307     controller1.DoLock();
308     controller1.waitForLockToBeHeld();
309     controller1.DoNotifyAll();
310     controller1.DoUnlock();
311     // Wait for controller3 to have locked.
312     // We cannot use waitForLockToBeHeld since we could race with the HANDLER waitForLockToBeHeld
313     // function.
314     unlocked_sem.release();
315     continue_sem.acquire();
316     controller3.DoUnlock();
317     controller2.waitForLockToBeHeld();
318     controller2.DoUnlock();
319   }
320 
testMonitorInfoInEvents(Monitors.NamedLock lk)321   public static void testMonitorInfoInEvents(Monitors.NamedLock lk) throws Exception {
322     final Monitors.LockController controller1 = new Monitors.LockController(lk);
323     final Monitors.LockController controller2 = new Monitors.LockController(lk);
324     HANDLER = new MonitorHandler() {
325       @Override public void handleMonitorEnter(Thread thd, Object l) {
326         System.out.println("Monitor usage in MonitorEnter: " + Monitors.getObjectMonitorUsage(l));
327       }
328       @Override public void handleMonitorEntered(Thread thd, Object l) {
329         System.out.println("Monitor usage in MonitorEntered: " + Monitors.getObjectMonitorUsage(l));
330       }
331       @Override public void handleMonitorWait(Thread thd, Object l, long timeout) {
332         System.out.println("Monitor usage in MonitorWait: " + Monitors.getObjectMonitorUsage(l));
333       }
334       @Override public void handleMonitorWaited(Thread thd, Object l, boolean timeout) {
335         // make sure that controller1 has acutally unlocked everything, we can be sent earlier than
336         // that on ART.
337         while (controller1.IsLocked()) {}
338         System.out.println("Monitor usage in MonitorWaited: " + Monitors.getObjectMonitorUsage(l));
339       }
340     };
341     controller1.DoLock();
342     controller1.waitForLockToBeHeld();
343     controller2.DoLock();
344     controller2.waitForContendedSleep();
345     controller1.DoUnlock();
346     controller2.waitForLockToBeHeld();
347     controller2.DoWait();
348     controller2.waitForNotifySleep();
349     controller1.DoLock();
350     controller1.waitForLockToBeHeld();
351     controller1.DoNotifyAll();
352     controller1.DoUnlock();
353     controller2.waitForLockToBeHeld();
354     controller2.DoUnlock();
355   }
356 
testThrowWaitedInterrupt(Monitors.NamedLock lk)357   public static void testThrowWaitedInterrupt(Monitors.NamedLock lk) throws Exception {
358     final Monitors.LockController controller1 = new Monitors.LockController(lk);
359     HANDLER = new MonitorHandler() {
360       @Override public void handleMonitorWaited(Thread thd, Object l, boolean timeout) {
361         System.out.println("Throwing exception in MonitorWaited");
362         throw new Monitors.TestException("throwing exception during monitorWaited of " + l);
363       }
364     };
365     controller1.DoLock();
366     controller1.waitForLockToBeHeld();
367     try {
368       controller1.DoWait();
369       controller1.waitForNotifySleep();
370       controller1.interruptWorker();
371       controller1.waitForLockToBeHeld();
372       controller1.DoUnlock();
373       System.out.println("No Exception thrown!");
374     } catch (Monitors.TestException e) {
375       printExceptions(e);
376       System.out.println("lock state is: " + Monitors.getObjectMonitorUsage(lk));
377       controller1.DoCleanup();
378     }
379   }
380 
testThrowWaitedTimeout(Monitors.NamedLock lk)381   public static void testThrowWaitedTimeout(Monitors.NamedLock lk) throws Exception {
382     final Monitors.LockController controller1 = new Monitors.LockController(lk, 5 * 1000);
383     HANDLER = new MonitorHandler() {
384       @Override public void handleMonitorWaited(Thread thd, Object l, boolean timeout) {
385         System.out.println("Throwing exception in MonitorWaited");
386         throw new Monitors.TestException("throwing exception during monitorWaited of " + l);
387       }
388     };
389     controller1.DoLock();
390     controller1.waitForLockToBeHeld();
391     try {
392       controller1.DoTimedWait();
393       controller1.waitForNotifySleep();
394       controller1.waitForLockToBeHeld();
395       controller1.DoUnlock();
396       System.out.println("No Exception thrown!");
397     } catch (Monitors.TestException e) {
398       printExceptions(e);
399       System.out.println("lock state is: " + Monitors.getObjectMonitorUsage(lk));
400       controller1.DoCleanup();
401     }
402   }
403 
testThrowWaited(Monitors.NamedLock lk)404   public static void testThrowWaited(Monitors.NamedLock lk) throws Exception {
405     final Monitors.LockController controller1 = new Monitors.LockController(lk);
406     final Monitors.LockController controller2 = new Monitors.LockController(lk);
407     HANDLER = new MonitorHandler() {
408       @Override public void handleMonitorWaited(Thread thd, Object l, boolean timeout) {
409         System.out.println("Throwing exception in MonitorWaited");
410         throw new Monitors.TestException("throwing exception during monitorWaited of " + l);
411       }
412     };
413     controller1.DoLock();
414     controller1.waitForLockToBeHeld();
415     controller1.DoWait();
416     controller1.waitForNotifySleep();
417 
418     controller2.DoLock();
419     controller2.waitForLockToBeHeld();
420     controller2.DoNotifyAll();
421     controller2.DoUnlock();
422     try {
423       controller1.waitForLockToBeHeld();
424       controller1.DoUnlock();
425       System.out.println("No Exception thrown!");
426     } catch (Monitors.TestException e) {
427       printExceptions(e);
428       System.out.println("lock state is: " + Monitors.getObjectMonitorUsage(lk));
429       controller1.DoCleanup();
430     }
431   }
432 
testThrowWait(final Monitors.NamedLock lk)433   public static void testThrowWait(final Monitors.NamedLock lk) throws Exception {
434     final Monitors.LockController controller1 = new Monitors.LockController(lk);
435     HANDLER = new MonitorHandler() {
436       @Override public void handleMonitorWait(Thread thd, Object l, long timeout) {
437         System.out.println("Throwing exception in MonitorWait");
438         throw new Monitors.TestException("throwing exception during MonitorWait of " + l);
439       }
440     };
441     controller1.DoLock();
442     controller1.waitForLockToBeHeld();
443     try {
444       controller1.DoWait();
445       controller1.waitForNotifySleep();
446       controller1.waitForLockToBeHeld();
447       controller1.DoUnlock();
448       System.out.println("No Exception thrown!");
449     } catch (Monitors.TestException e) {
450       printExceptions(e);
451       System.out.println("lock state is: " + Monitors.getObjectMonitorUsage(lk));
452       controller1.DoCleanup();
453     }
454   }
455 
testThrowIllegalWait(final Monitors.NamedLock lk)456   public static void testThrowIllegalWait(final Monitors.NamedLock lk) throws Exception {
457     final Monitors.LockController controller1 = new Monitors.LockController(lk, -100000);
458     HANDLER = new MonitorHandler() {
459       @Override public void handleMonitorWait(Thread thd, Object l, long timeout) {
460         System.out.println("Throwing exception in MonitorWait timeout = " + timeout);
461         throw new Monitors.TestException("throwing exception during monitorWait of " + l);
462       }
463     };
464     try {
465       controller1.DoLock();
466       controller1.waitForLockToBeHeld();
467       controller1.DoTimedWait();
468       controller1.waitForLockToBeHeld();
469       controller1.DoUnlock();
470       System.out.println("No Exception thrown!");
471     } catch (Monitors.TestException e) {
472       printExceptions(e);
473       System.out.println("lock state is: " + Monitors.getObjectMonitorUsage(lk));
474       controller1.DoCleanup();
475     }
476   }
477 
testLockUncontend(final Monitors.NamedLock lk)478   public static void testLockUncontend(final Monitors.NamedLock lk) throws Exception {
479     final Monitors.LockController controller1 = new Monitors.LockController(lk);
480     final Monitors.LockController controller2 = new Monitors.LockController(lk);
481     HANDLER = new MonitorHandler() {
482       @Override public void handleMonitorEnter(Thread thd, Object lock) {
483         if (controller1.IsLocked()) {
484           System.out.println("Releasing " + lk + " during monitorEnter event.");
485           try {
486             controller1.DoUnlock();
487           } catch (Exception e) {
488             throw new Error("Unable to unlock controller1", e);
489           }
490         } else {
491           throw new Error("controller1 does not seem to hold the lock!");
492         }
493       }
494     };
495     controller1.DoLock();
496     controller1.waitForLockToBeHeld();
497     // This will call handleMonitorEnter but will release during the callback.
498     controller2.DoLock();
499     controller2.waitForLockToBeHeld();
500     if (controller1.IsLocked()) {
501       throw new Error("controller1 still holds the lock somehow!");
502     }
503     controller2.DoUnlock();
504   }
505 
testLockThrowEnter(Monitors.NamedLock lk)506   public static void testLockThrowEnter(Monitors.NamedLock lk) throws Exception {
507     Monitors.LockController controller1 = new Monitors.LockController(lk);
508     Monitors.LockController controller2 = new Monitors.LockController(lk);
509     HANDLER = new MonitorHandler() {
510       @Override public void handleMonitorEnter(Thread t, Object l) {
511         System.out.println("Throwing exception in MonitorEnter");
512         throw new Monitors.TestException("throwing exception during monitorEnter of " + l);
513       }
514     };
515     controller1.DoLock();
516     controller1.waitForLockToBeHeld();
517     try {
518       controller2.DoLock();
519       controller2.waitForContendedSleep();
520       controller1.DoUnlock();
521       controller2.waitForLockToBeHeld();
522       controller2.DoUnlock();
523       System.out.println("Did not get an exception!");
524     } catch (Monitors.TestException e) {
525       printExceptions(e);
526       System.out.println("lock state is: " + Monitors.getObjectMonitorUsage(lk));
527       controller2.DoCleanup();
528     }
529   }
530 
testLockThrowEntered(Monitors.NamedLock lk)531   public static void testLockThrowEntered(Monitors.NamedLock lk) throws Exception {
532     Monitors.LockController controller1 = new Monitors.LockController(lk);
533     Monitors.LockController controller2 = new Monitors.LockController(lk);
534     HANDLER = new MonitorHandler() {
535       @Override public void handleMonitorEntered(Thread t, Object l) {
536         System.out.println("Throwing exception in MonitorEntered");
537         throw new Monitors.TestException("throwing exception during monitorEntered of " + l);
538       }
539     };
540     controller1.DoLock();
541     controller1.waitForLockToBeHeld();
542     try {
543       controller2.DoLock();
544       controller2.waitForContendedSleep();
545       controller1.DoUnlock();
546       controller2.waitForLockToBeHeld();
547       controller2.DoUnlock();
548       System.out.println("Did not get an exception!");
549     } catch (Monitors.TestException e) {
550       printExceptions(e);
551       System.out.println("lock state is: " + Monitors.getObjectMonitorUsage(lk));
552       controller2.DoCleanup();
553     }
554   }
555 
testLockThrowBoth(Monitors.NamedLock lk)556   public static void testLockThrowBoth(Monitors.NamedLock lk) throws Exception {
557     Monitors.LockController controller1 = new Monitors.LockController(lk);
558     Monitors.LockController controller2 = new Monitors.LockController(lk);
559     HANDLER = new MonitorHandler() {
560       @Override public void handleMonitorEnter(Thread t, Object l) {
561         System.out.println("Throwing exception in MonitorEnter");
562         throw new Monitors.TestException("throwing exception during monitorEnter of " + l);
563       }
564       @Override public void handleMonitorEntered(Thread t, Object l) {
565         System.out.println("Throwing exception in MonitorEntered");
566         throw new Monitors.TestException("throwing exception during monitorEntered of " + l);
567       }
568     };
569     controller1.DoLock();
570     controller1.waitForLockToBeHeld();
571     try {
572       controller2.DoLock();
573       controller2.waitForContendedSleep();
574       controller1.DoUnlock();
575       controller2.waitForLockToBeHeld();
576       controller2.DoUnlock();
577       System.out.println("Did not get an exception!");
578     } catch (Monitors.TestException e) {
579       printExceptions(e);
580       System.out.println("lock state is: " + Monitors.getObjectMonitorUsage(lk));
581       controller2.DoCleanup();
582     }
583   }
584 
printExceptions(Throwable t)585   public static void printExceptions(Throwable t) {
586     System.out.println("Caught exception: " + t);
587     for (Throwable c = t.getCause(); c != null; c = c.getCause()) {
588       System.out.println("\tCaused by: " +
589           (Test1932.class.getPackage().equals(c.getClass().getPackage())
590            ? c.toString() : c.getClass().toString()));
591     }
592     if (PRINT_FULL_STACK_TRACE) {
593       t.printStackTrace();
594     }
595   }
596 
handleMonitorEnter(Thread thd, Object lock)597   public static void handleMonitorEnter(Thread thd, Object lock) {
598     System.out.println(thd.getName() + " contended-LOCKING " + lock);
599     if (HANDLER != null) {
600       HANDLER.handleMonitorEnter(thd, lock);
601     }
602   }
603 
handleMonitorEntered(Thread thd, Object lock)604   public static void handleMonitorEntered(Thread thd, Object lock) {
605     System.out.println(thd.getName() + " LOCKED " + lock);
606     if (HANDLER != null) {
607       HANDLER.handleMonitorEntered(thd, lock);
608     }
609   }
handleMonitorWait(Thread thd, Object lock, long timeout)610   public static void handleMonitorWait(Thread thd, Object lock, long timeout) {
611     System.out.println(thd.getName() + " start-monitor-wait " + lock + " timeout: " + timeout);
612     if (HANDLER != null) {
613       HANDLER.handleMonitorWait(thd, lock, timeout);
614     }
615   }
616 
handleMonitorWaited(Thread thd, Object lock, boolean timed_out)617   public static void handleMonitorWaited(Thread thd, Object lock, boolean timed_out) {
618     System.out.println(thd.getName() + " monitor-waited " + lock + " timed_out: " + timed_out);
619     if (HANDLER != null) {
620       HANDLER.handleMonitorWaited(thd, lock, timed_out);
621     }
622   }
623 }
624