jdk/test/javax/management/notification/BroadcasterSupportDeadlockTest.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2004-2005 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    21  * have any questions.
       
    22  */
       
    23 
       
    24 /*
       
    25  * @test
       
    26  * @bug 5093922 2120055
       
    27  * @summary Test that NotificationBroadcasterSupport can be subclassed
       
    28  * and used with synchronized(this) without causing deadlock
       
    29  * @author Eamonn McManus
       
    30  * @run clean BroadcasterSupportDeadlockTest
       
    31  * @run build BroadcasterSupportDeadlockTest
       
    32  * @run main BroadcasterSupportDeadlockTest
       
    33  */
       
    34 
       
    35 import java.lang.management.*;
       
    36 import java.util.concurrent.*;
       
    37 import javax.management.*;
       
    38 
       
    39 public class BroadcasterSupportDeadlockTest {
       
    40     public static void main(String[] args) throws Exception {
       
    41         try {
       
    42             Class.forName(ManagementFactory.class.getName());
       
    43         } catch (Throwable t) {
       
    44             System.out.println("TEST CANNOT RUN: needs JDK 5 at least");
       
    45             return;
       
    46         }
       
    47 
       
    48         final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
       
    49         final BroadcasterMBean mbean = new Broadcaster();
       
    50         final ObjectName name = new ObjectName("test:type=Broadcaster");
       
    51         mbs.registerMBean(mbean, name);
       
    52 
       
    53         ThreadMXBean threads = ManagementFactory.getThreadMXBean();
       
    54         threads.setThreadContentionMonitoringEnabled(true);
       
    55 
       
    56         final Semaphore semaphore = new Semaphore(0);
       
    57 
       
    58         // Thread 1 - block the Broadcaster
       
    59         Thread t1 = new Thread() {
       
    60             public void run() {
       
    61                 try {
       
    62                     mbs.invoke(name, "block",
       
    63                                new Object[] {semaphore},
       
    64                                new String[] {Semaphore.class.getName()});
       
    65                 } catch (Exception e) {
       
    66                     e.printStackTrace(System.out);
       
    67                 } finally {
       
    68                     System.out.println("TEST INCORRECT: block returned");
       
    69                     System.exit(1);
       
    70                 }
       
    71             }
       
    72         };
       
    73         t1.setDaemon(true);
       
    74         t1.start();
       
    75 
       
    76         /* Wait for Thread 1 to be doing Object.wait().  It's very
       
    77            difficult to synchronize properly here so we wait for the
       
    78            semaphore, then wait a little longer for the mbs.invoke to
       
    79            run, then just in case that isn't enough, we wait for the
       
    80            thread to be in WAITING state.  This isn't foolproof,
       
    81            because the machine could be very slow and the
       
    82            Thread.getState() could find the thread in WAITING state
       
    83            due to some operation it does on its way to the one we're
       
    84            interested in.  */
       
    85         semaphore.acquire();
       
    86         Thread.sleep(100);
       
    87         while (t1.getState() != Thread.State.WAITING)
       
    88             Thread.sleep(1);
       
    89 
       
    90         // Thread 2 - try to add a listener
       
    91         final NotificationListener listener = new NotificationListener() {
       
    92             public void handleNotification(Notification n, Object h) {}
       
    93         };
       
    94         Thread t2 = new Thread() {
       
    95             public void run() {
       
    96                 try {
       
    97                     mbs.addNotificationListener(name, listener, null, null);
       
    98                 } catch (Exception e) {
       
    99                     System.out.println("TEST INCORRECT: addNL failed:");
       
   100                     e.printStackTrace(System.out);
       
   101                 }
       
   102             }
       
   103         };
       
   104         t2.setDaemon(true);
       
   105         t2.start();
       
   106 
       
   107         /* Wait for Thread 2 to be blocked on the monitor or to
       
   108            succeed.  */
       
   109         Thread.sleep(100);
       
   110 
       
   111         for (int i = 0; i < 1000/*ms*/; i++) {
       
   112             t2.join(1/*ms*/);
       
   113             switch (t2.getState()) {
       
   114             case TERMINATED:
       
   115                 System.out.println("TEST PASSED");
       
   116                 return;
       
   117             case BLOCKED:
       
   118                 java.util.Map<Thread,StackTraceElement[]> traces =
       
   119                     Thread.getAllStackTraces();
       
   120                 showStackTrace("Thread 1", traces.get(t1));
       
   121                 showStackTrace("Thread 2", traces.get(t2));
       
   122                 System.out.println("TEST FAILED: deadlock");
       
   123                 System.exit(1);
       
   124                 break;
       
   125             default:
       
   126                 break;
       
   127             }
       
   128         }
       
   129 
       
   130         System.out.println("TEST FAILED BUT DID NOT NOTICE DEADLOCK");
       
   131         Thread.sleep(10000);
       
   132         System.exit(1);
       
   133     }
       
   134 
       
   135     private static void showStackTrace(String title,
       
   136                                        StackTraceElement[] stack) {
       
   137         System.out.println("---" + title + "---");
       
   138         if (stack == null)
       
   139             System.out.println("<no stack trace???>");
       
   140         else {
       
   141             for (StackTraceElement elmt : stack)
       
   142                 System.out.println("    " + elmt);
       
   143         }
       
   144         System.out.println();
       
   145     }
       
   146 
       
   147     public static interface BroadcasterMBean {
       
   148         public void block(Semaphore semaphore);
       
   149     }
       
   150 
       
   151     public static class Broadcaster
       
   152             extends NotificationBroadcasterSupport
       
   153             implements BroadcasterMBean {
       
   154         public synchronized void block(Semaphore semaphore) {
       
   155             Object lock = new Object();
       
   156             synchronized (lock) {
       
   157                 try {
       
   158                     // Let the caller know that it can now wait for us to
       
   159                     // hit the WAITING state
       
   160                     semaphore.release();
       
   161                     lock.wait(); // block forever
       
   162                 } catch (InterruptedException e) {
       
   163                     System.out.println("TEST INCORRECT: lock interrupted:");
       
   164                     e.printStackTrace(System.out);
       
   165                     System.exit(1);
       
   166                 }
       
   167             }
       
   168         }
       
   169     }
       
   170 }