aoqi@0: /* aoqi@0: * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: /* aoqi@0: * @test aoqi@0: * @bug 8036823 aoqi@0: * @bug 8046287 aoqi@0: * @summary Creates two threads contending for the same lock and checks aoqi@0: * whether jstack reports "locked" by more than one thread. aoqi@0: * aoqi@0: * @library /testlibrary aoqi@0: * @run main/othervm TestThreadDumpMonitorContention aoqi@0: */ aoqi@0: aoqi@0: import java.io.BufferedReader; aoqi@0: import java.io.InputStreamReader; aoqi@0: import java.lang.management.ManagementFactory; aoqi@0: import java.lang.management.RuntimeMXBean; aoqi@0: import java.util.ArrayList; aoqi@0: import java.util.List; aoqi@0: import java.util.regex.Matcher; aoqi@0: import java.util.regex.Pattern; aoqi@0: aoqi@0: import com.oracle.java.testlibrary.*; aoqi@0: aoqi@0: public class TestThreadDumpMonitorContention { aoqi@0: // jstack tends to be closely bound to the VM that we are running aoqi@0: // so use getTestJDKTool() instead of getCompileJDKTool() or even aoqi@0: // getJDKTool() which can fall back to "compile.jdk". aoqi@0: final static String JSTACK = JDKToolFinder.getTestJDKTool("jstack"); aoqi@0: final static String PID = getPid(); aoqi@0: aoqi@0: // looking for header lines with these patterns: aoqi@0: // "ContendingThread-1" #19 prio=5 os_prio=64 tid=0x000000000079c000 nid=0x23 runnable [0xffff80ffb8b87000] aoqi@0: // "ContendingThread-2" #21 prio=5 os_prio=64 tid=0x0000000000780000 nid=0x2f waiting for monitor entry [0xfffffd7fc1111000] aoqi@0: // "ContendingThread-2" #24 prio=5 os_prio=64 tid=0x0000000000ec8800 nid=0x31 waiting on condition [0xfffffd7bbfffe000] aoqi@0: final static Pattern HEADER_PREFIX_PATTERN = Pattern.compile( aoqi@0: "^\"ContendingThread-.*"); aoqi@0: final static Pattern HEADER_WAITING_PATTERN1 = Pattern.compile( aoqi@0: "^\"ContendingThread-.* waiting for monitor entry .*"); aoqi@0: final static Pattern HEADER_WAITING_PATTERN2 = Pattern.compile( aoqi@0: "^\"ContendingThread-.* waiting on condition .*"); aoqi@0: final static Pattern HEADER_RUNNABLE_PATTERN = Pattern.compile( aoqi@0: "^\"ContendingThread-.* runnable .*"); aoqi@0: aoqi@0: // looking for thread state lines with these patterns: aoqi@0: // java.lang.Thread.State: RUNNABLE aoqi@0: // java.lang.Thread.State: BLOCKED (on object monitor) aoqi@0: final static Pattern THREAD_STATE_PREFIX_PATTERN = Pattern.compile( aoqi@0: " *java\\.lang\\.Thread\\.State: .*"); aoqi@0: final static Pattern THREAD_STATE_BLOCKED_PATTERN = Pattern.compile( aoqi@0: " *java\\.lang\\.Thread\\.State: BLOCKED \\(on object monitor\\)"); aoqi@0: final static Pattern THREAD_STATE_RUNNABLE_PATTERN = Pattern.compile( aoqi@0: " *java\\.lang\\.Thread\\.State: RUNNABLE"); aoqi@0: aoqi@0: // looking for duplicates of this pattern: aoqi@0: // - locked <0x000000076ac59e20> (a TestThreadDumpMonitorContention$1) aoqi@0: final static Pattern LOCK_PATTERN = Pattern.compile( aoqi@0: ".* locked \\<.*\\(a TestThreadDumpMonitorContention.*"); aoqi@0: aoqi@0: // sanity checking header and thread state lines associated aoqi@0: // with this pattern: aoqi@0: // - waiting to lock <0x000000076ac59e20> (a TestThreadDumpMonitorContention$1) aoqi@0: final static Pattern WAITING_PATTERN = Pattern.compile( aoqi@0: ".* waiting to lock \\<.*\\(a TestThreadDumpMonitorContention.*"); aoqi@0: aoqi@0: final static Object barrier = new Object(); aoqi@0: volatile static boolean done = false; aoqi@0: aoqi@0: static int barrier_cnt = 0; aoqi@0: static int blank_line_match_cnt = 0; aoqi@0: static int error_cnt = 0; aoqi@0: static boolean have_header_line = false; aoqi@0: static boolean have_thread_state_line = false; aoqi@0: static String header_line = null; aoqi@0: static int header_prefix_match_cnt = 0; aoqi@0: static int locked_line_match_cnt = 0; aoqi@0: static String[] locked_match_list = new String[2]; aoqi@0: static int n_samples = 15; aoqi@0: static int sum_both_running_cnt = 0; aoqi@0: static int sum_both_waiting_cnt = 0; aoqi@0: static int sum_contended_cnt = 0; aoqi@0: static int sum_locked_hdr_runnable_cnt = 0; aoqi@0: static int sum_locked_hdr_waiting1_cnt = 0; aoqi@0: static int sum_locked_hdr_waiting2_cnt = 0; aoqi@0: static int sum_locked_thr_state_blocked_cnt = 0; aoqi@0: static int sum_locked_thr_state_runnable_cnt = 0; aoqi@0: static int sum_one_waiting_cnt = 0; aoqi@0: static int sum_uncontended_cnt = 0; aoqi@0: static int sum_waiting_hdr_waiting1_cnt = 0; aoqi@0: static int sum_waiting_thr_state_blocked_cnt = 0; aoqi@0: static String thread_state_line = null; aoqi@0: static boolean verbose = false; aoqi@0: static int waiting_line_match_cnt = 0; aoqi@0: aoqi@0: public static void main(String[] args) throws Exception { aoqi@0: if (args.length != 0) { aoqi@0: int arg_i = 0; aoqi@0: if (args[arg_i].equals("-v")) { aoqi@0: verbose = true; aoqi@0: arg_i++; aoqi@0: } aoqi@0: aoqi@0: try { aoqi@0: n_samples = Integer.parseInt(args[arg_i]); aoqi@0: } catch (NumberFormatException nfe) { aoqi@0: System.err.println(nfe); aoqi@0: usage(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: Runnable runnable = new Runnable() { aoqi@0: public void run() { aoqi@0: synchronized (barrier) { aoqi@0: // let the main thread know we're running aoqi@0: barrier_cnt++; aoqi@0: barrier.notify(); aoqi@0: } aoqi@0: while (!done) { aoqi@0: synchronized (this) { } aoqi@0: } aoqi@0: } aoqi@0: }; aoqi@0: Thread[] thread_list = new Thread[2]; aoqi@0: thread_list[0] = new Thread(runnable, "ContendingThread-1"); aoqi@0: thread_list[1] = new Thread(runnable, "ContendingThread-2"); aoqi@0: synchronized (barrier) { aoqi@0: thread_list[0].start(); aoqi@0: thread_list[1].start(); aoqi@0: aoqi@0: // Wait until the contending threads are running so that aoqi@0: // we don't sample any thread init states. aoqi@0: while (barrier_cnt < 2) { aoqi@0: barrier.wait(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: doSamples(); aoqi@0: aoqi@0: done = true; aoqi@0: aoqi@0: thread_list[0].join(); aoqi@0: thread_list[1].join(); aoqi@0: aoqi@0: if (error_cnt == 0) { aoqi@0: System.out.println("Test PASSED."); aoqi@0: } else { aoqi@0: System.out.println("Test FAILED."); aoqi@0: throw new AssertionError("error_cnt=" + error_cnt); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Reached a blank line which is the end of the aoqi@0: // stack trace without matching either LOCK_PATTERN aoqi@0: // or WAITING_PATTERN. Rare, but it's not an error. aoqi@0: // aoqi@0: // Example: aoqi@0: // "ContendingThread-1" #21 prio=5 os_prio=64 tid=0x00000000007b9000 nid=0x2f runnable [0xfffffd7fc1111000] aoqi@0: // java.lang.Thread.State: RUNNABLE aoqi@0: // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:140) aoqi@0: // at java.lang.Thread.run(Thread.java:745) aoqi@0: // aoqi@0: static boolean checkBlankLine(String line) { aoqi@0: if (line.length() == 0) { aoqi@0: blank_line_match_cnt++; aoqi@0: have_header_line = false; aoqi@0: have_thread_state_line = false; aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: // Process the locked line here if we found one. aoqi@0: // aoqi@0: // Example 1: aoqi@0: // "ContendingThread-1" #21 prio=5 os_prio=64 tid=0x00000000007b9000 nid=0x2f runnable [0xfffffd7fc1111000] aoqi@0: // java.lang.Thread.State: RUNNABLE aoqi@0: // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:140) aoqi@0: // - locked <0xfffffd7e6a2912f8> (a TestThreadDumpMonitorContention$1) aoqi@0: // at java.lang.Thread.run(Thread.java:745) aoqi@0: // aoqi@0: // Example 2: aoqi@0: // "ContendingThread-1" #21 prio=5 os_prio=64 tid=0x00000000007b9000 nid=0x2f waiting for monitor entry [0xfffffd7fc1111000] aoqi@0: // java.lang.Thread.State: BLOCKED (on object monitor) aoqi@0: // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:140) aoqi@0: // - locked <0xfffffd7e6a2912f8> (a TestThreadDumpMonitorContention$1) aoqi@0: // at java.lang.Thread.run(Thread.java:745) aoqi@0: // aoqi@0: // Example 3: aoqi@0: // "ContendingThread-2" #24 prio=5 os_prio=64 tid=0x0000000000ec8800 nid=0x31 waiting on condition [0xfffffd7bbfffe000] aoqi@0: // java.lang.Thread.State: RUNNABLE aoqi@0: // JavaThread state: _thread_blocked aoqi@0: // Thread: 0x0000000000ec8800 [0x31] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0 aoqi@0: // JavaThread state: _thread_blocked aoqi@0: // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:140) aoqi@0: // - locked <0xfffffd7e6d03eb28> (a TestThreadDumpMonitorContention$1) aoqi@0: // at java.lang.Thread.run(Thread.java:745) aoqi@0: // aoqi@0: static boolean checkLockedLine(String line) { aoqi@0: Matcher matcher = LOCK_PATTERN.matcher(line); aoqi@0: if (matcher.matches()) { aoqi@0: if (verbose) { aoqi@0: System.out.println("locked_line='" + line + "'"); aoqi@0: } aoqi@0: locked_match_list[locked_line_match_cnt] = new String(line); aoqi@0: locked_line_match_cnt++; aoqi@0: aoqi@0: matcher = HEADER_RUNNABLE_PATTERN.matcher(header_line); aoqi@0: if (matcher.matches()) { aoqi@0: sum_locked_hdr_runnable_cnt++; aoqi@0: } else { aoqi@0: // It's strange, but a locked line can also aoqi@0: // match the HEADER_WAITING_PATTERN{1,2}. aoqi@0: matcher = HEADER_WAITING_PATTERN1.matcher(header_line); aoqi@0: if (matcher.matches()) { aoqi@0: sum_locked_hdr_waiting1_cnt++; aoqi@0: } else { aoqi@0: matcher = HEADER_WAITING_PATTERN2.matcher(header_line); aoqi@0: if (matcher.matches()) { aoqi@0: sum_locked_hdr_waiting2_cnt++; aoqi@0: } else { aoqi@0: System.err.println(); aoqi@0: System.err.println("ERROR: header line does " + aoqi@0: "not match runnable or waiting patterns."); aoqi@0: System.err.println("ERROR: header_line='" + aoqi@0: header_line + "'"); aoqi@0: System.err.println("ERROR: locked_line='" + line + aoqi@0: "'"); aoqi@0: error_cnt++; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: matcher = THREAD_STATE_RUNNABLE_PATTERN.matcher(thread_state_line); aoqi@0: if (matcher.matches()) { aoqi@0: sum_locked_thr_state_runnable_cnt++; aoqi@0: } else { aoqi@0: // It's strange, but a locked line can also aoqi@0: // match the THREAD_STATE_BLOCKED_PATTERN. aoqi@0: matcher = THREAD_STATE_BLOCKED_PATTERN.matcher( aoqi@0: thread_state_line); aoqi@0: if (matcher.matches()) { aoqi@0: sum_locked_thr_state_blocked_cnt++; aoqi@0: } else { aoqi@0: System.err.println(); aoqi@0: System.err.println("ERROR: thread state line does not " + aoqi@0: "match runnable or waiting patterns."); aoqi@0: System.err.println("ERROR: " + "thread_state_line='" + aoqi@0: thread_state_line + "'"); aoqi@0: System.err.println("ERROR: locked_line='" + line + "'"); aoqi@0: error_cnt++; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // Have everything we need from this thread stack aoqi@0: // that matches the LOCK_PATTERN. aoqi@0: have_header_line = false; aoqi@0: have_thread_state_line = false; aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: // Process the waiting line here if we found one. aoqi@0: // aoqi@0: // Example: aoqi@0: // "ContendingThread-2" #22 prio=5 os_prio=64 tid=0x00000000007b9800 nid=0x30 waiting for monitor entry [0xfffffd7fc1010000] aoqi@0: // java.lang.Thread.State: BLOCKED (on object monitor) aoqi@0: // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:140) aoqi@0: // - waiting to lock <0xfffffd7e6a2912f8> (a TestThreadDumpMonitorContention$1) aoqi@0: // at java.lang.Thread.run(Thread.java:745) aoqi@0: // aoqi@0: static boolean checkWaitingLine(String line) { aoqi@0: Matcher matcher = WAITING_PATTERN.matcher(line); aoqi@0: if (matcher.matches()) { aoqi@0: waiting_line_match_cnt++; aoqi@0: if (verbose) { aoqi@0: System.out.println("waiting_line='" + line + "'"); aoqi@0: } aoqi@0: aoqi@0: matcher = HEADER_WAITING_PATTERN1.matcher(header_line); aoqi@0: if (matcher.matches()) { aoqi@0: sum_waiting_hdr_waiting1_cnt++; aoqi@0: } else { aoqi@0: System.err.println(); aoqi@0: System.err.println("ERROR: header line does " + aoqi@0: "not match a waiting pattern."); aoqi@0: System.err.println("ERROR: header_line='" + header_line + "'"); aoqi@0: System.err.println("ERROR: waiting_line='" + line + "'"); aoqi@0: error_cnt++; aoqi@0: } aoqi@0: aoqi@0: matcher = THREAD_STATE_BLOCKED_PATTERN.matcher(thread_state_line); aoqi@0: if (matcher.matches()) { aoqi@0: sum_waiting_thr_state_blocked_cnt++; aoqi@0: } else { aoqi@0: System.err.println(); aoqi@0: System.err.println("ERROR: thread state line " + aoqi@0: "does not match a waiting pattern."); aoqi@0: System.err.println("ERROR: thread_state_line='" + aoqi@0: thread_state_line + "'"); aoqi@0: System.err.println("ERROR: waiting_line='" + line + "'"); aoqi@0: error_cnt++; aoqi@0: } aoqi@0: aoqi@0: // Have everything we need from this thread stack aoqi@0: // that matches the WAITING_PATTERN. aoqi@0: have_header_line = false; aoqi@0: have_thread_state_line = false; aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: static void doSamples() throws Exception { aoqi@0: for (int count = 0; count < n_samples; count++) { aoqi@0: blank_line_match_cnt = 0; aoqi@0: header_prefix_match_cnt = 0; aoqi@0: locked_line_match_cnt = 0; aoqi@0: waiting_line_match_cnt = 0; aoqi@0: // verbose mode or an error has a lot of output so add more space aoqi@0: if (verbose || error_cnt > 0) System.out.println(); aoqi@0: System.out.println("Sample #" + count); aoqi@0: aoqi@0: // We don't use the ProcessTools, OutputBuffer or aoqi@0: // OutputAnalyzer classes from the testlibrary because aoqi@0: // we have a complicated multi-line parse to perform aoqi@0: // on a narrow subset of the JSTACK output. aoqi@0: // aoqi@0: // - we only care about stack traces that match aoqi@0: // HEADER_PREFIX_PATTERN; only two should match aoqi@0: // - we care about at most three lines from each stack trace aoqi@0: // - if both stack traces match LOCKED_PATTERN, then that's aoqi@0: // a failure and we report it aoqi@0: // - for a stack trace that matches LOCKED_PATTERN, we verify: aoqi@0: // - the header line matches HEADER_RUNNABLE_PATTERN aoqi@0: // or HEADER_WAITING_PATTERN{1,2} aoqi@0: // - the thread state line matches THREAD_STATE_BLOCKED_PATTERN aoqi@0: // or THREAD_STATE_RUNNABLE_PATTERN aoqi@0: // - we report any mismatches as failures aoqi@0: // - for a stack trace that matches WAITING_PATTERN, we verify: aoqi@0: // - the header line matches HEADER_WAITING_PATTERN1 aoqi@0: // - the thread state line matches THREAD_STATE_BLOCKED_PATTERN aoqi@0: // - we report any mismatches as failures aoqi@0: // - the stack traces that match HEADER_PREFIX_PATTERN may aoqi@0: // not match either LOCKED_PATTERN or WAITING_PATTERN aoqi@0: // because we might observe the thread outside of aoqi@0: // monitor operations; this is not considered a failure aoqi@0: // aoqi@0: // When we do observe LOCKED_PATTERN or WAITING_PATTERN, aoqi@0: // then we are checking the header and thread state patterns aoqi@0: // that occurred earlier in the current stack trace that aoqi@0: // matched HEADER_PREFIX_PATTERN. We don't use data from aoqi@0: // stack traces that don't match HEADER_PREFIX_PATTERN and aoqi@0: // we don't mix data between the two stack traces that do aoqi@0: // match HEADER_PREFIX_PATTERN. aoqi@0: // aoqi@0: Process process = new ProcessBuilder(JSTACK, PID) aoqi@0: .redirectErrorStream(true).start(); aoqi@0: aoqi@0: BufferedReader reader = new BufferedReader(new InputStreamReader( aoqi@0: process.getInputStream())); aoqi@0: String line; aoqi@0: while ((line = reader.readLine()) != null) { aoqi@0: Matcher matcher = null; aoqi@0: aoqi@0: // process the header line here aoqi@0: if (!have_header_line) { aoqi@0: matcher = HEADER_PREFIX_PATTERN.matcher(line); aoqi@0: if (matcher.matches()) { aoqi@0: header_prefix_match_cnt++; aoqi@0: if (verbose) { aoqi@0: System.out.println(); aoqi@0: System.out.println("header='" + line + "'"); aoqi@0: } aoqi@0: header_line = new String(line); aoqi@0: have_header_line = true; aoqi@0: continue; aoqi@0: } aoqi@0: continue; // skip until have a header line aoqi@0: } aoqi@0: aoqi@0: // process the thread state line here aoqi@0: if (!have_thread_state_line) { aoqi@0: matcher = THREAD_STATE_PREFIX_PATTERN.matcher(line); aoqi@0: if (matcher.matches()) { aoqi@0: if (verbose) { aoqi@0: System.out.println("thread_state='" + line + "'"); aoqi@0: } aoqi@0: thread_state_line = new String(line); aoqi@0: have_thread_state_line = true; aoqi@0: continue; aoqi@0: } aoqi@0: continue; // skip until we have a thread state line aoqi@0: } aoqi@0: aoqi@0: // process the locked line here if we find one aoqi@0: if (checkLockedLine(line)) { aoqi@0: continue; aoqi@0: } aoqi@0: aoqi@0: // process the waiting line here if we find one aoqi@0: if (checkWaitingLine(line)) { aoqi@0: continue; aoqi@0: } aoqi@0: aoqi@0: // process the blank line here if we find one aoqi@0: if (checkBlankLine(line)) { aoqi@0: continue; aoqi@0: } aoqi@0: } aoqi@0: process.waitFor(); aoqi@0: aoqi@0: if (header_prefix_match_cnt != 2) { aoqi@0: System.err.println(); aoqi@0: System.err.println("ERROR: should match exactly two headers."); aoqi@0: System.err.println("ERROR: header_prefix_match_cnt=" + aoqi@0: header_prefix_match_cnt); aoqi@0: error_cnt++; aoqi@0: } aoqi@0: aoqi@0: if (locked_line_match_cnt == 2) { aoqi@0: if (locked_match_list[0].equals(locked_match_list[1])) { aoqi@0: System.err.println(); aoqi@0: System.err.println("ERROR: matching lock lines:"); aoqi@0: System.err.println("ERROR: line[0]'" + aoqi@0: locked_match_list[0] + "'"); aoqi@0: System.err.println("ERROR: line[1]'" + aoqi@0: locked_match_list[1] + "'"); aoqi@0: error_cnt++; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (locked_line_match_cnt == 1) { aoqi@0: // one thread has the lock aoqi@0: if (waiting_line_match_cnt == 1) { aoqi@0: // and the other contended for it aoqi@0: sum_contended_cnt++; aoqi@0: } else { aoqi@0: // and the other is just running aoqi@0: sum_uncontended_cnt++; aoqi@0: } aoqi@0: } else if (waiting_line_match_cnt == 1) { aoqi@0: // one thread is waiting aoqi@0: sum_one_waiting_cnt++; aoqi@0: } else if (waiting_line_match_cnt == 2) { aoqi@0: // both threads are waiting aoqi@0: sum_both_waiting_cnt++; aoqi@0: } else { aoqi@0: // both threads are running aoqi@0: sum_both_running_cnt++; aoqi@0: } aoqi@0: aoqi@0: // slight delay between jstack launches aoqi@0: Thread.sleep(500); aoqi@0: } aoqi@0: aoqi@0: if (error_cnt != 0) { aoqi@0: // skip summary info since there were errors aoqi@0: return; aoqi@0: } aoqi@0: aoqi@0: System.out.println("INFO: Summary for all samples:"); aoqi@0: System.out.println("INFO: both_running_cnt=" + sum_both_running_cnt); aoqi@0: System.out.println("INFO: both_waiting_cnt=" + sum_both_waiting_cnt); aoqi@0: System.out.println("INFO: contended_cnt=" + sum_contended_cnt); aoqi@0: System.out.println("INFO: one_waiting_cnt=" + sum_one_waiting_cnt); aoqi@0: System.out.println("INFO: uncontended_cnt=" + sum_uncontended_cnt); aoqi@0: System.out.println("INFO: locked_hdr_runnable_cnt=" + aoqi@0: sum_locked_hdr_runnable_cnt); aoqi@0: System.out.println("INFO: locked_hdr_waiting1_cnt=" + aoqi@0: sum_locked_hdr_waiting1_cnt); aoqi@0: System.out.println("INFO: locked_hdr_waiting2_cnt=" + aoqi@0: sum_locked_hdr_waiting2_cnt); aoqi@0: System.out.println("INFO: locked_thr_state_blocked_cnt=" + aoqi@0: sum_locked_thr_state_blocked_cnt); aoqi@0: System.out.println("INFO: locked_thr_state_runnable_cnt=" + aoqi@0: sum_locked_thr_state_runnable_cnt); aoqi@0: System.out.println("INFO: waiting_hdr_waiting1_cnt=" + aoqi@0: sum_waiting_hdr_waiting1_cnt); aoqi@0: System.out.println("INFO: waiting_thr_state_blocked_cnt=" + aoqi@0: sum_waiting_thr_state_blocked_cnt); aoqi@0: aoqi@0: if (sum_contended_cnt == 0) { aoqi@0: System.err.println("WARNING: the primary scenario for 8036823" + aoqi@0: " has not been exercised by this test run."); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // This helper relies on RuntimeMXBean.getName() returning a string aoqi@0: // that looks like this: 5436@mt-haku aoqi@0: // aoqi@0: // The testlibrary has tryFindJvmPid(), but that uses a separate aoqi@0: // process which is much more expensive for finding out your own PID. aoqi@0: // aoqi@0: static String getPid() { aoqi@0: RuntimeMXBean runtimebean = ManagementFactory.getRuntimeMXBean(); aoqi@0: String vmname = runtimebean.getName(); aoqi@0: int i = vmname.indexOf('@'); aoqi@0: if (i != -1) { aoqi@0: vmname = vmname.substring(0, i); aoqi@0: } aoqi@0: return vmname; aoqi@0: } aoqi@0: aoqi@0: static void usage() { aoqi@0: System.err.println("Usage: " + aoqi@0: "java TestThreadDumpMonitorContention [-v] [n_samples]"); aoqi@0: System.exit(1); aoqi@0: } aoqi@0: }