Mon, 17 Jun 2013 18:35:44 +0200
8016304: ThreadMXBean.getDeadlockedThreads reports bogus deadlocks on JDK 8
Reviewed-by: dcubed, mgronlun
src/share/vm/services/threadService.cpp | file | annotate | diff | comparison | revisions | |
test/serviceability/threads/TestFalseDeadLock.java | file | annotate | diff | comparison | revisions |
1.1 --- a/src/share/vm/services/threadService.cpp Mon Jun 10 10:45:19 2013 -0400 1.2 +++ b/src/share/vm/services/threadService.cpp Mon Jun 17 18:35:44 2013 +0200 1.3 @@ -327,27 +327,30 @@ 1.4 while (waitingToLockMonitor != NULL || waitingToLockBlocker != NULL) { 1.5 cycle->add_thread(currentThread); 1.6 if (waitingToLockMonitor != NULL) { 1.7 - currentThread = Threads::owning_thread_from_monitor_owner( 1.8 - (address)waitingToLockMonitor->owner(), 1.9 - false /* no locking needed */); 1.10 - if (currentThread == NULL) { 1.11 - // This function is called at a safepoint so the JavaThread 1.12 - // that owns waitingToLockMonitor should be findable, but 1.13 - // if it is not findable, then the previous currentThread is 1.14 - // blocked permanently. We record this as a deadlock. 1.15 - num_deadlocks++; 1.16 + address currentOwner = (address)waitingToLockMonitor->owner(); 1.17 + if (currentOwner != NULL) { 1.18 + currentThread = Threads::owning_thread_from_monitor_owner( 1.19 + currentOwner, 1.20 + false /* no locking needed */); 1.21 + if (currentThread == NULL) { 1.22 + // This function is called at a safepoint so the JavaThread 1.23 + // that owns waitingToLockMonitor should be findable, but 1.24 + // if it is not findable, then the previous currentThread is 1.25 + // blocked permanently. We record this as a deadlock. 1.26 + num_deadlocks++; 1.27 1.28 - cycle->set_deadlock(true); 1.29 + cycle->set_deadlock(true); 1.30 1.31 - // add this cycle to the deadlocks list 1.32 - if (deadlocks == NULL) { 1.33 - deadlocks = cycle; 1.34 - } else { 1.35 - last->set_next(cycle); 1.36 + // add this cycle to the deadlocks list 1.37 + if (deadlocks == NULL) { 1.38 + deadlocks = cycle; 1.39 + } else { 1.40 + last->set_next(cycle); 1.41 + } 1.42 + last = cycle; 1.43 + cycle = new DeadlockCycle(); 1.44 + break; 1.45 } 1.46 - last = cycle; 1.47 - cycle = new DeadlockCycle(); 1.48 - break; 1.49 } 1.50 } else { 1.51 if (concurrent_locks) {
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/serviceability/threads/TestFalseDeadLock.java Mon Jun 17 18:35:44 2013 +0200 2.3 @@ -0,0 +1,95 @@ 2.4 +/* 2.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.23 + * or visit www.oracle.com if you need additional information or have any 2.24 + * questions. 2.25 + */ 2.26 + 2.27 +import java.lang.management.ManagementFactory; 2.28 +import java.lang.management.ThreadMXBean; 2.29 +import java.util.Random; 2.30 + 2.31 +/* 2.32 + * @test 2.33 + * @bug 8016304 2.34 + * @summary Make sure no deadlock is reported for this program which has no deadlocks. 2.35 + * @run main/othervm TestFalseDeadLock 2.36 + */ 2.37 + 2.38 +/* 2.39 + * This test will not provoke the bug every time it is run since the bug is intermittent. 2.40 + * The test has a fixed running time of 5 seconds. 2.41 + */ 2.42 + 2.43 +public class TestFalseDeadLock { 2.44 + private static ThreadMXBean bean; 2.45 + private static volatile boolean running = true; 2.46 + private static volatile boolean found = false; 2.47 + 2.48 + public static void main(String[] args) throws Exception { 2.49 + bean = ManagementFactory.getThreadMXBean(); 2.50 + Thread[] threads = new Thread[500]; 2.51 + for (int i = 0; i < threads.length; i++) { 2.52 + Test t = new Test(); 2.53 + threads[i] = new Thread(t); 2.54 + threads[i].start(); 2.55 + } 2.56 + try { 2.57 + Thread.sleep(5000); 2.58 + } catch (InterruptedException ex) { 2.59 + } 2.60 + running = false; 2.61 + for (Thread t : threads) { 2.62 + t.join(); 2.63 + } 2.64 + if (found) { 2.65 + throw new Exception("Deadlock reported, but there is no deadlock."); 2.66 + } 2.67 + } 2.68 + 2.69 + public static class Test implements Runnable { 2.70 + public void run() { 2.71 + Random r = new Random(); 2.72 + while (running) { 2.73 + try { 2.74 + synchronized (this) { 2.75 + wait(r.nextInt(1000) + 1); 2.76 + } 2.77 + } catch (InterruptedException ex) { 2.78 + } 2.79 + recurse(2000); 2.80 + } 2.81 + if (bean.findDeadlockedThreads() != null) { 2.82 + System.out.println("FOUND!"); 2.83 + found = true; 2.84 + } 2.85 + } 2.86 + 2.87 + private void recurse(int i) { 2.88 + if (!running) { 2.89 + // It is important for the test to call println here 2.90 + // since there are locks inside that path. 2.91 + System.out.println("Hullo"); 2.92 + } 2.93 + else if (i > 0) { 2.94 + recurse(i - 1); 2.95 + } 2.96 + } 2.97 + } 2.98 +}