1 /* 2 * Copyright (c) 2010, 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 import java.lang.management.ThreadInfo; 24 import java.lang.management.ThreadMXBean; 25 import java.lang.Thread.State; 26 import java.io.IOException; 27 import java.lang.management.ManagementFactory; 28 import java.util.logging.LogManager; 29 import java.util.logging.Logger; 30 import java.util.Map; 31 32 /** 33 * @test 34 * @bug 8010939 35 * @author jim.gish@oracle.com 36 * @run main/timeout=15 Bug8010939 37 */ 38 public class Bug8010939 { 39 private LogManager mgr = LogManager.getLogManager(); 40 private final static int MAX_ITERATIONS=1000; 41 private ThreadMXBean threadMXBean = null; 42 private boolean threadMXBeanDeadlockSupported = true; // assume true for now 43 private static volatile boolean deadlockDetected = false; 44 45 public static void main(String... args) throws IOException, Exception { 46 new Bug8010939().testForDeadlock(); 47 if (deadlockDetected) { 48 System.out.println( "Deadlock detected."); 49 } 50 } 51 52 public static void randomDelay() { 53 int runs = (int) Math.random() * 1000000; 54 int c = 0; 55 56 for (int i = 0; i < runs; ++i) { 57 c = c + i; 58 } 59 } 60 61 public void testForDeadlock() throws IOException, Exception { 62 // Get a ThreadMXBean so we can check for deadlock. N.B. this may 63 // not be supported on all platforms, which means we will have to 64 // resort to the traditional test timeout method. However, if 65 // we have the support we'll get the deadlock details if one 66 // is detected. 67 threadMXBean = ManagementFactory.getThreadMXBean(); 68 69 Thread setup = new Thread( new SetupLogger(), "SetupLogger" ); 70 Thread readConfig = new Thread( new ReadConfig(), "ReadConfig" ); 71 Thread check = new Thread( new DeadlockChecker(setup, readConfig), 72 "DeadlockChecker" ); 73 74 setup.start(); readConfig.start(); check.start(); 75 try { 76 check.join(); 77 } catch (InterruptedException ex) { 78 ex.printStackTrace(); 79 } 80 if (deadlockDetected) { 81 throw new Exception( "TEST FAILED: Deadlock detected" ); 82 } 83 try { 84 readConfig.join(); 85 setup.join(); 86 } catch (InterruptedException ex) { 87 ex.printStackTrace(); 88 } 89 System.out.println("Test passed"); 90 } 91 92 class SetupLogger implements Runnable { 93 Logger logger = null; 94 95 @Override 96 public void run() { 97 for (int i=0;i<MAX_ITERATIONS; i++) { 98 logger = Logger.getLogger("Bug8010939"+i); 99 mgr.addLogger(logger); 100 Bug8010939.randomDelay(); 101 } 102 } 103 } 104 105 class ReadConfig implements Runnable { 106 @Override 107 public void run() { 108 for (int i=0; i<MAX_ITERATIONS; i++) { 109 try { 110 mgr.readConfiguration(); 111 } catch (Exception ex) { 112 ex.printStackTrace(); 113 } 114 Bug8010939.randomDelay(); 115 } 116 } 117 } 118 119 class DeadlockChecker implements Runnable { 120 Thread t1, t2; 121 122 DeadlockChecker(Thread t1, Thread t2) { 123 this.t1 = t1; 124 this.t2 = t2; 125 } 126 127 boolean checkState( Thread x, Thread y ) { 128 System.out.println( "In checkState" ); 129 boolean isXblocked = x.getState().equals(State.BLOCKED); 130 boolean isYblocked = y.getState().equals(State.BLOCKED); 131 long[] deadlockedThreads = null; 132 boolean isDeadlocked = false; // until we find out otherwise 133 134 if (isXblocked && isYblocked ) { 135 // they are both blocked, but this doesn't necessarily mean 136 // they are deadlocked 137 if (threadMXBeanDeadlockSupported) { 138 try { 139 deadlockedThreads = threadMXBean.findDeadlockedThreads(); 140 } catch (UnsupportedOperationException ex) { 141 System.out.println( "INFO: This platform does not support " + 142 "ThreadMXBean.findDeadlockedThreads() " + 143 "so, we'll continue waiting for test timeout."); 144 threadMXBeanDeadlockSupported = false; 145 } 146 } 147 if (deadlockedThreads != null) { 148 System.out.println( "We detected a deadlock! "); 149 ThreadInfo[] threadInfos = threadMXBean.getThreadInfo( 150 deadlockedThreads, true, true); 151 for (ThreadInfo threadInfo: threadInfos) { 152 System.out.println( threadInfo ); 153 } 154 return true; // we know we're deadlocked 155 } 156 System.out.println( "We may have a deadlock"); 157 Map<Thread, StackTraceElement[]> threadMap = 158 Thread.getAllStackTraces(); 159 dumpStack( threadMap.get(x), x); 160 dumpStack( threadMap.get(y), y); 161 } 162 return isDeadlocked; 163 } 164 165 private void dumpStack(StackTraceElement[] aStackElt, Thread aThread) { 166 if (aStackElt != null) { 167 System.out.println( "Thread:" + aThread.getName() + ": " + 168 aThread.getState()); 169 for (StackTraceElement element: aStackElt) { 170 System.out.println( " " + element ); 171 } 172 } 173 } 174 175 @Override 176 public void run() { 177 boolean deadlockFound = false; 178 for (int i=0; i<MAX_ITERATIONS && !deadlockFound ; i++) { 179 deadlockFound = checkState(t1, t2); 180 Bug8010939.randomDelay(); 181 } 182 if (deadlockFound) { 183 deadlockDetected = true; 184 } 185 } 186 } 187 }