Thu, 05 Jun 2014 06:40:35 +0000
Merge
1.1 --- a/src/share/vm/opto/bytecodeInfo.cpp Fri May 30 06:50:38 2014 +0200 1.2 +++ b/src/share/vm/opto/bytecodeInfo.cpp Thu Jun 05 06:40:35 2014 +0000 1.3 @@ -361,11 +361,14 @@ 1.4 set_msg("not an accessor"); 1.5 return false; 1.6 } 1.7 + 1.8 + // Limit inlining depth in case inlining is forced or 1.9 + // _max_inline_level was increased to compensate for lambda forms. 1.10 + if (inline_level() > MaxForceInlineLevel) { 1.11 + set_msg("MaxForceInlineLevel"); 1.12 + return false; 1.13 + } 1.14 if (inline_level() > _max_inline_level) { 1.15 - if (callee_method->force_inline() && inline_level() > MaxForceInlineLevel) { 1.16 - set_msg("MaxForceInlineLevel"); 1.17 - return false; 1.18 - } 1.19 if (!callee_method->force_inline() || !IncrementalInline) { 1.20 set_msg("inlining too deep"); 1.21 return false;
2.1 --- a/src/share/vm/runtime/objectMonitor.cpp Fri May 30 06:50:38 2014 +0200 2.2 +++ b/src/share/vm/runtime/objectMonitor.cpp Thu Jun 05 06:40:35 2014 +0000 2.3 @@ -418,6 +418,15 @@ 2.4 jt->java_suspend_self(); 2.5 } 2.6 Self->set_current_pending_monitor(NULL); 2.7 + 2.8 + // We cleared the pending monitor info since we've just gotten past 2.9 + // the enter-check-for-suspend dance and we now own the monitor free 2.10 + // and clear, i.e., it is no longer pending. The ThreadBlockInVM 2.11 + // destructor can go to a safepoint at the end of this block. If we 2.12 + // do a thread dump during that safepoint, then this thread will show 2.13 + // as having "-locked" the monitor, but the OS and java.lang.Thread 2.14 + // states will still report that the thread is blocked trying to 2.15 + // acquire it. 2.16 } 2.17 2.18 Atomic::dec_ptr(&_count);
3.1 --- a/src/share/vm/runtime/vframe.cpp Fri May 30 06:50:38 2014 +0200 3.2 +++ b/src/share/vm/runtime/vframe.cpp Thu Jun 05 06:40:35 2014 +0000 3.3 @@ -199,6 +199,7 @@ 3.4 continue; 3.5 } 3.6 if (monitor->owner() != NULL) { 3.7 + // the monitor is associated with an object, i.e., it is locked 3.8 3.9 // First, assume we have the monitor locked. If we haven't found an 3.10 // owned monitor before and this is the first frame, then we need to 3.11 @@ -209,7 +210,11 @@ 3.12 if (!found_first_monitor && frame_count == 0) { 3.13 markOop mark = monitor->owner()->mark(); 3.14 if (mark->has_monitor() && 3.15 - mark->monitor() == thread()->current_pending_monitor()) { 3.16 + ( // we have marked ourself as pending on this monitor 3.17 + mark->monitor() == thread()->current_pending_monitor() || 3.18 + // we are not the owner of this monitor 3.19 + !mark->monitor()->is_entered(thread()) 3.20 + )) { 3.21 lock_state = "waiting to lock"; 3.22 } 3.23 }
4.1 --- a/test/TEST.groups Fri May 30 06:50:38 2014 +0200 4.2 +++ b/test/TEST.groups Thu Jun 05 06:40:35 2014 +0000 4.3 @@ -1,5 +1,5 @@ 4.4 # 4.5 -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 4.6 +# Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. 4.7 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.8 # 4.9 # This code is free software; you can redistribute it and/or modify it 4.10 @@ -84,6 +84,7 @@ 4.11 runtime/NMT/ThreadedVirtualAllocTestType.java \ 4.12 runtime/NMT/VirtualAllocTestType.java \ 4.13 runtime/RedefineObject/TestRedefineObject.java \ 4.14 + runtime/Thread/TestThreadDumpMonitorContention.java \ 4.15 runtime/XCheckJniJsig/XCheckJSig.java \ 4.16 serviceability/attach/AttachWithStalePidFile.java \ 4.17 serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/runtime/Thread/TestThreadDumpMonitorContention.java Thu Jun 05 06:40:35 2014 +0000 5.3 @@ -0,0 +1,405 @@ 5.4 +/* 5.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + */ 5.26 + 5.27 +/* 5.28 + * @test 5.29 + * @bug 8036823 5.30 + * @summary Creates two threads contending for the same lock and checks 5.31 + * whether jstack reports "locked" by more than one thread. 5.32 + * 5.33 + * @library /testlibrary 5.34 + * @run main/othervm TestThreadDumpMonitorContention 5.35 + */ 5.36 + 5.37 +import java.io.BufferedReader; 5.38 +import java.io.InputStreamReader; 5.39 +import java.lang.management.ManagementFactory; 5.40 +import java.lang.management.RuntimeMXBean; 5.41 +import java.util.ArrayList; 5.42 +import java.util.List; 5.43 +import java.util.regex.Matcher; 5.44 +import java.util.regex.Pattern; 5.45 + 5.46 +import com.oracle.java.testlibrary.*; 5.47 + 5.48 +public class TestThreadDumpMonitorContention { 5.49 + // jstack tends to be closely bound to the VM that we are running 5.50 + // so use getTestJDKTool() instead of getCompileJDKTool() or even 5.51 + // getJDKTool() which can fall back to "compile.jdk". 5.52 + final static String JSTACK = JDKToolFinder.getTestJDKTool("jstack"); 5.53 + final static String PID = getPid(); 5.54 + 5.55 + // looking for header lines with these patterns: 5.56 + // "ContendingThread-1" #19 prio=5 os_prio=64 tid=0x000000000079c000 nid=0x23 runnable [0xffff80ffb8b87000] 5.57 + // "ContendingThread-2" #21 prio=5 os_prio=64 tid=0x0000000000780000 nid=0x2f waiting for monitor entry [0xfffffd7fc1111000] 5.58 + final static Pattern HEADER_PREFIX_PATTERN = Pattern.compile( 5.59 + "^\"ContendingThread-.*"); 5.60 + final static Pattern HEADER_WAITING_PATTERN = Pattern.compile( 5.61 + "^\"ContendingThread-.* waiting for monitor entry .*"); 5.62 + final static Pattern HEADER_RUNNABLE_PATTERN = Pattern.compile( 5.63 + "^\"ContendingThread-.* runnable .*"); 5.64 + 5.65 + // looking for thread state lines with these patterns: 5.66 + // java.lang.Thread.State: RUNNABLE 5.67 + // java.lang.Thread.State: BLOCKED (on object monitor) 5.68 + final static Pattern THREAD_STATE_PREFIX_PATTERN = Pattern.compile( 5.69 + " *java\\.lang\\.Thread\\.State: .*"); 5.70 + final static Pattern THREAD_STATE_BLOCKED_PATTERN = Pattern.compile( 5.71 + " *java\\.lang\\.Thread\\.State: BLOCKED \\(on object monitor\\)"); 5.72 + final static Pattern THREAD_STATE_RUNNABLE_PATTERN = Pattern.compile( 5.73 + " *java\\.lang\\.Thread\\.State: RUNNABLE"); 5.74 + 5.75 + // looking for duplicates of this pattern: 5.76 + // - locked <0x000000076ac59e20> (a TestThreadDumpMonitorContention$1) 5.77 + final static Pattern LOCK_PATTERN = Pattern.compile( 5.78 + ".* locked \\<.*\\(a TestThreadDumpMonitorContention.*"); 5.79 + 5.80 + // sanity checking header and thread state lines associated 5.81 + // with this pattern: 5.82 + // - waiting to lock <0x000000076ac59e20> (a TestThreadDumpMonitorContention$1) 5.83 + final static Pattern WAITING_PATTERN = Pattern.compile( 5.84 + ".* waiting to lock \\<.*\\(a TestThreadDumpMonitorContention.*"); 5.85 + 5.86 + volatile static boolean done = false; 5.87 + 5.88 + static int error_cnt = 0; 5.89 + static String header_line = null; 5.90 + static boolean have_header_line = false; 5.91 + static boolean have_thread_state_line = false; 5.92 + static int match_cnt = 0; 5.93 + static String[] match_list = new String[2]; 5.94 + static int n_samples = 15; 5.95 + static String thread_state_line = null; 5.96 + static boolean verbose = false; 5.97 + 5.98 + public static void main(String[] args) throws Exception { 5.99 + if (args.length != 0) { 5.100 + int arg_i = 0; 5.101 + if (args[arg_i].equals("-v")) { 5.102 + verbose = true; 5.103 + arg_i++; 5.104 + } 5.105 + 5.106 + try { 5.107 + n_samples = Integer.parseInt(args[arg_i]); 5.108 + } catch (NumberFormatException nfe) { 5.109 + System.err.println(nfe); 5.110 + usage(); 5.111 + } 5.112 + } 5.113 + 5.114 + Runnable runnable = new Runnable() { 5.115 + public void run() { 5.116 + while (!done) { 5.117 + synchronized (this) { } 5.118 + } 5.119 + } 5.120 + }; 5.121 + Thread[] thread_list = new Thread[2]; 5.122 + thread_list[0] = new Thread(runnable, "ContendingThread-1"); 5.123 + thread_list[1] = new Thread(runnable, "ContendingThread-2"); 5.124 + thread_list[0].start(); 5.125 + thread_list[1].start(); 5.126 + 5.127 + doSamples(); 5.128 + 5.129 + done = true; 5.130 + 5.131 + thread_list[0].join(); 5.132 + thread_list[1].join(); 5.133 + 5.134 + if (error_cnt == 0) { 5.135 + System.out.println("Test PASSED."); 5.136 + } else { 5.137 + System.out.println("Test FAILED."); 5.138 + throw new AssertionError("error_cnt=" + error_cnt); 5.139 + } 5.140 + } 5.141 + 5.142 + // Reached a blank line which is the end of the 5.143 + // stack trace without matching either LOCK_PATTERN 5.144 + // or WAITING_PATTERN. Rare, but it's not an error. 5.145 + // 5.146 + // Example: 5.147 + // "ContendingThread-1" #21 prio=5 os_prio=64 tid=0x00000000007b9000 nid=0x2f runnable [0xfffffd7fc1111000] 5.148 + // java.lang.Thread.State: RUNNABLE 5.149 + // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:67) 5.150 + // at java.lang.Thread.run(Thread.java:745) 5.151 + // 5.152 + static boolean checkBlankLine(String line) { 5.153 + if (line.length() == 0) { 5.154 + have_header_line = false; 5.155 + have_thread_state_line = false; 5.156 + return true; 5.157 + } 5.158 + 5.159 + return false; 5.160 + } 5.161 + 5.162 + // Process the locked line here if we found one. 5.163 + // 5.164 + // Example 1: 5.165 + // "ContendingThread-1" #21 prio=5 os_prio=64 tid=0x00000000007b9000 nid=0x2f runnable [0xfffffd7fc1111000] 5.166 + // java.lang.Thread.State: RUNNABLE 5.167 + // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:67) 5.168 + // - locked <0xfffffd7e6a2912f8> (a TestThreadDumpMonitorContention$1) 5.169 + // at java.lang.Thread.run(Thread.java:745) 5.170 + // 5.171 + // Example 2: 5.172 + // "ContendingThread-1" #21 prio=5 os_prio=64 tid=0x00000000007b9000 nid=0x2f waiting for monitor entry [0xfffffd7fc1111000] 5.173 + // java.lang.Thread.State: BLOCKED (on object monitor) 5.174 + // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:67) 5.175 + // - locked <0xfffffd7e6a2912f8> (a TestThreadDumpMonitorContention$1) 5.176 + // at java.lang.Thread.run(Thread.java:745) 5.177 + // 5.178 + static boolean checkLockedLine(String line) { 5.179 + Matcher matcher = LOCK_PATTERN.matcher(line); 5.180 + if (matcher.matches()) { 5.181 + if (verbose) { 5.182 + System.out.println("locked_line='" + line + "'"); 5.183 + } 5.184 + match_list[match_cnt] = new String(line); 5.185 + match_cnt++; 5.186 + 5.187 + matcher = HEADER_RUNNABLE_PATTERN.matcher(header_line); 5.188 + if (!matcher.matches()) { 5.189 + // It's strange, but a locked line can also 5.190 + // match the HEADER_WAITING_PATTERN. 5.191 + matcher = HEADER_WAITING_PATTERN.matcher(header_line); 5.192 + if (!matcher.matches()) { 5.193 + System.err.println(); 5.194 + System.err.println("ERROR: header line does " + 5.195 + "not match runnable or waiting patterns."); 5.196 + System.err.println("ERROR: header_line='" + 5.197 + header_line + "'"); 5.198 + System.err.println("ERROR: locked_line='" + line + "'"); 5.199 + error_cnt++; 5.200 + } 5.201 + } 5.202 + 5.203 + matcher = THREAD_STATE_RUNNABLE_PATTERN.matcher(thread_state_line); 5.204 + if (!matcher.matches()) { 5.205 + // It's strange, but a locked line can also 5.206 + // match the THREAD_STATE_BLOCKED_PATTERN. 5.207 + matcher = THREAD_STATE_BLOCKED_PATTERN.matcher( 5.208 + thread_state_line); 5.209 + if (!matcher.matches()) { 5.210 + System.err.println(); 5.211 + System.err.println("ERROR: thread state line does not " + 5.212 + "match runnable or waiting patterns."); 5.213 + System.err.println("ERROR: " + "thread_state_line='" + 5.214 + thread_state_line + "'"); 5.215 + System.err.println("ERROR: locked_line='" + line + "'"); 5.216 + error_cnt++; 5.217 + } 5.218 + } 5.219 + 5.220 + // Have everything we need from this thread stack 5.221 + // that matches the LOCK_PATTERN. 5.222 + have_header_line = false; 5.223 + have_thread_state_line = false; 5.224 + return true; 5.225 + } 5.226 + 5.227 + return false; 5.228 + } 5.229 + 5.230 + // Process the waiting line here if we found one. 5.231 + // 5.232 + // Example: 5.233 + // "ContendingThread-2" #22 prio=5 os_prio=64 tid=0x00000000007b9800 nid=0x30 waiting for monitor entry [0xfffffd7fc1010000] 5.234 + // java.lang.Thread.State: BLOCKED (on object monitor) 5.235 + // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:67) 5.236 + // - waiting to lock <0xfffffd7e6a2912f8> (a TestThreadDumpMonitorContention$1) 5.237 + // at java.lang.Thread.run(Thread.java:745) 5.238 + // 5.239 + static boolean checkWaitingLine(String line) { 5.240 + Matcher matcher = WAITING_PATTERN.matcher(line); 5.241 + if (matcher.matches()) { 5.242 + if (verbose) { 5.243 + System.out.println("waiting_line='" + line + "'"); 5.244 + } 5.245 + 5.246 + matcher = HEADER_WAITING_PATTERN.matcher(header_line); 5.247 + if (!matcher.matches()) { 5.248 + System.err.println(); 5.249 + System.err.println("ERROR: header line does " + 5.250 + "not match a waiting pattern."); 5.251 + System.err.println("ERROR: header_line='" + header_line + "'"); 5.252 + System.err.println("ERROR: waiting_line='" + line + "'"); 5.253 + error_cnt++; 5.254 + } 5.255 + 5.256 + matcher = THREAD_STATE_BLOCKED_PATTERN.matcher(thread_state_line); 5.257 + if (!matcher.matches()) { 5.258 + System.err.println(); 5.259 + System.err.println("ERROR: thread state line " + 5.260 + "does not match a waiting pattern."); 5.261 + System.err.println("ERROR: thread_state_line='" + 5.262 + thread_state_line + "'"); 5.263 + System.err.println("ERROR: waiting_line='" + line + "'"); 5.264 + error_cnt++; 5.265 + } 5.266 + 5.267 + // Have everything we need from this thread stack 5.268 + // that matches the WAITING_PATTERN. 5.269 + have_header_line = false; 5.270 + have_thread_state_line = false; 5.271 + return true; 5.272 + } 5.273 + 5.274 + return false; 5.275 + } 5.276 + 5.277 + static void doSamples() throws Exception { 5.278 + for (int count = 0; count < n_samples; count++) { 5.279 + match_cnt = 0; 5.280 + // verbose mode or an error has a lot of output so add more space 5.281 + if (verbose || error_cnt > 0) System.out.println(); 5.282 + System.out.println("Sample #" + count); 5.283 + 5.284 + // We don't use the ProcessTools, OutputBuffer or 5.285 + // OutputAnalyzer classes from the testlibrary because 5.286 + // we have a complicated multi-line parse to perform 5.287 + // on a narrow subset of the JSTACK output. 5.288 + // 5.289 + // - we only care about stack traces that match 5.290 + // HEADER_PREFIX_PATTERN; only two should match 5.291 + // - we care about at most three lines from each stack trace 5.292 + // - if both stack traces match LOCKED_PATTERN, then that's 5.293 + // a failure and we report it 5.294 + // - for a stack trace that matches LOCKED_PATTERN, we verify: 5.295 + // - the header line matches HEADER_RUNNABLE_PATTERN 5.296 + // or HEADER_WAITING_PATTERN 5.297 + // - the thread state line matches THREAD_STATE_BLOCKED_PATTERN 5.298 + // or THREAD_STATE_RUNNABLE_PATTERN 5.299 + // - we report any mismatches as failures 5.300 + // - for a stack trace that matches WAITING_PATTERN, we verify: 5.301 + // - the header line matches HEADER_WAITING_PATTERN 5.302 + // - the thread state line matches THREAD_STATE_BLOCKED_PATTERN 5.303 + // - we report any mismatches as failures 5.304 + // - the stack traces that match HEADER_PREFIX_PATTERN may 5.305 + // not match either LOCKED_PATTERN or WAITING_PATTERN 5.306 + // because we might observe the thread outside of 5.307 + // monitor operations; this is not considered a failure 5.308 + // 5.309 + // When we do observe LOCKED_PATTERN or WAITING_PATTERN, 5.310 + // then we are checking the header and thread state patterns 5.311 + // that occurred earlier in the current stack trace that 5.312 + // matched HEADER_PREFIX_PATTERN. We don't use data from 5.313 + // stack traces that don't match HEADER_PREFIX_PATTERN and 5.314 + // we don't mix data between the two stack traces that do 5.315 + // match HEADER_PREFIX_PATTERN. 5.316 + // 5.317 + Process process = new ProcessBuilder(JSTACK, PID) 5.318 + .redirectErrorStream(true).start(); 5.319 + 5.320 + BufferedReader reader = new BufferedReader(new InputStreamReader( 5.321 + process.getInputStream())); 5.322 + String line; 5.323 + while ((line = reader.readLine()) != null) { 5.324 + Matcher matcher = null; 5.325 + 5.326 + // process the header line here 5.327 + if (!have_header_line) { 5.328 + matcher = HEADER_PREFIX_PATTERN.matcher(line); 5.329 + if (matcher.matches()) { 5.330 + if (verbose) { 5.331 + System.out.println(); 5.332 + System.out.println("header='" + line + "'"); 5.333 + } 5.334 + header_line = new String(line); 5.335 + have_header_line = true; 5.336 + continue; 5.337 + } 5.338 + continue; // skip until have a header line 5.339 + } 5.340 + 5.341 + // process the thread state line here 5.342 + if (!have_thread_state_line) { 5.343 + matcher = THREAD_STATE_PREFIX_PATTERN.matcher(line); 5.344 + if (matcher.matches()) { 5.345 + if (verbose) { 5.346 + System.out.println("thread_state='" + line + "'"); 5.347 + } 5.348 + thread_state_line = new String(line); 5.349 + have_thread_state_line = true; 5.350 + continue; 5.351 + } 5.352 + continue; // skip until we have a thread state line 5.353 + } 5.354 + 5.355 + // process the locked line here if we find one 5.356 + if (checkLockedLine(line)) { 5.357 + continue; 5.358 + } 5.359 + 5.360 + // process the waiting line here if we find one 5.361 + if (checkWaitingLine(line)) { 5.362 + continue; 5.363 + } 5.364 + 5.365 + // process the blank line here if we find one 5.366 + if (checkBlankLine(line)) { 5.367 + continue; 5.368 + } 5.369 + } 5.370 + process.waitFor(); 5.371 + 5.372 + if (match_cnt == 2) { 5.373 + if (match_list[0].equals(match_list[1])) { 5.374 + System.err.println(); 5.375 + System.err.println("ERROR: matching lock lines:"); 5.376 + System.err.println("ERROR: line[0]'" + match_list[0] + "'"); 5.377 + System.err.println("ERROR: line[1]'" + match_list[1] + "'"); 5.378 + error_cnt++; 5.379 + } 5.380 + } 5.381 + 5.382 + // slight delay between jstack launches 5.383 + Thread.sleep(500); 5.384 + } 5.385 + } 5.386 + 5.387 + // This helper relies on RuntimeMXBean.getName() returning a string 5.388 + // that looks like this: 5436@mt-haku 5.389 + // 5.390 + // The testlibrary has tryFindJvmPid(), but that uses a separate 5.391 + // process which is much more expensive for finding out your own PID. 5.392 + // 5.393 + static String getPid() { 5.394 + RuntimeMXBean runtimebean = ManagementFactory.getRuntimeMXBean(); 5.395 + String vmname = runtimebean.getName(); 5.396 + int i = vmname.indexOf('@'); 5.397 + if (i != -1) { 5.398 + vmname = vmname.substring(0, i); 5.399 + } 5.400 + return vmname; 5.401 + } 5.402 + 5.403 + static void usage() { 5.404 + System.err.println("Usage: " + 5.405 + "java TestThreadDumpMonitorContention [-v] [n_samples]"); 5.406 + System.exit(1); 5.407 + } 5.408 +}