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