|
1 /* |
|
2 * Copyright (c) 2014, 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 |
|
24 /* |
|
25 * @test |
|
26 * @bug 8036823 |
|
27 * @bug 8046287 |
|
28 * @summary Creates two threads contending for the same lock and checks |
|
29 * whether jstack reports "locked" by more than one thread. |
|
30 * |
|
31 * @library /testlibrary |
|
32 * @run main/othervm TestThreadDumpMonitorContention |
|
33 */ |
|
34 |
|
35 import java.io.BufferedReader; |
|
36 import java.io.InputStreamReader; |
|
37 import java.lang.management.ManagementFactory; |
|
38 import java.lang.management.RuntimeMXBean; |
|
39 import java.util.ArrayList; |
|
40 import java.util.List; |
|
41 import java.util.regex.Matcher; |
|
42 import java.util.regex.Pattern; |
|
43 |
|
44 import com.oracle.java.testlibrary.*; |
|
45 |
|
46 public class TestThreadDumpMonitorContention { |
|
47 // jstack tends to be closely bound to the VM that we are running |
|
48 // so use getTestJDKTool() instead of getCompileJDKTool() or even |
|
49 // getJDKTool() which can fall back to "compile.jdk". |
|
50 final static String JSTACK = JDKToolFinder.getTestJDKTool("jstack"); |
|
51 final static String PID = getPid(); |
|
52 |
|
53 // looking for header lines with these patterns: |
|
54 // "ContendingThread-1" #19 prio=5 os_prio=64 tid=0x000000000079c000 nid=0x23 runnable [0xffff80ffb8b87000] |
|
55 // "ContendingThread-2" #21 prio=5 os_prio=64 tid=0x0000000000780000 nid=0x2f waiting for monitor entry [0xfffffd7fc1111000] |
|
56 // "ContendingThread-2" #24 prio=5 os_prio=64 tid=0x0000000000ec8800 nid=0x31 waiting on condition [0xfffffd7bbfffe000] |
|
57 final static Pattern HEADER_PREFIX_PATTERN = Pattern.compile( |
|
58 "^\"ContendingThread-.*"); |
|
59 final static Pattern HEADER_WAITING_PATTERN1 = Pattern.compile( |
|
60 "^\"ContendingThread-.* waiting for monitor entry .*"); |
|
61 final static Pattern HEADER_WAITING_PATTERN2 = Pattern.compile( |
|
62 "^\"ContendingThread-.* waiting on condition .*"); |
|
63 final static Pattern HEADER_RUNNABLE_PATTERN = Pattern.compile( |
|
64 "^\"ContendingThread-.* runnable .*"); |
|
65 |
|
66 // looking for thread state lines with these patterns: |
|
67 // java.lang.Thread.State: RUNNABLE |
|
68 // java.lang.Thread.State: BLOCKED (on object monitor) |
|
69 final static Pattern THREAD_STATE_PREFIX_PATTERN = Pattern.compile( |
|
70 " *java\\.lang\\.Thread\\.State: .*"); |
|
71 final static Pattern THREAD_STATE_BLOCKED_PATTERN = Pattern.compile( |
|
72 " *java\\.lang\\.Thread\\.State: BLOCKED \\(on object monitor\\)"); |
|
73 final static Pattern THREAD_STATE_RUNNABLE_PATTERN = Pattern.compile( |
|
74 " *java\\.lang\\.Thread\\.State: RUNNABLE"); |
|
75 |
|
76 // looking for duplicates of this pattern: |
|
77 // - locked <0x000000076ac59e20> (a TestThreadDumpMonitorContention$1) |
|
78 final static Pattern LOCK_PATTERN = Pattern.compile( |
|
79 ".* locked \\<.*\\(a TestThreadDumpMonitorContention.*"); |
|
80 |
|
81 // sanity checking header and thread state lines associated |
|
82 // with this pattern: |
|
83 // - waiting to lock <0x000000076ac59e20> (a TestThreadDumpMonitorContention$1) |
|
84 final static Pattern WAITING_PATTERN = Pattern.compile( |
|
85 ".* waiting to lock \\<.*\\(a TestThreadDumpMonitorContention.*"); |
|
86 |
|
87 final static Object barrier = new Object(); |
|
88 volatile static boolean done = false; |
|
89 |
|
90 static int barrier_cnt = 0; |
|
91 static int blank_line_match_cnt = 0; |
|
92 static int error_cnt = 0; |
|
93 static boolean have_header_line = false; |
|
94 static boolean have_thread_state_line = false; |
|
95 static String header_line = null; |
|
96 static int header_prefix_match_cnt = 0; |
|
97 static int locked_line_match_cnt = 0; |
|
98 static String[] locked_match_list = new String[2]; |
|
99 static int n_samples = 15; |
|
100 static int sum_both_running_cnt = 0; |
|
101 static int sum_both_waiting_cnt = 0; |
|
102 static int sum_contended_cnt = 0; |
|
103 static int sum_locked_hdr_runnable_cnt = 0; |
|
104 static int sum_locked_hdr_waiting1_cnt = 0; |
|
105 static int sum_locked_hdr_waiting2_cnt = 0; |
|
106 static int sum_locked_thr_state_blocked_cnt = 0; |
|
107 static int sum_locked_thr_state_runnable_cnt = 0; |
|
108 static int sum_one_waiting_cnt = 0; |
|
109 static int sum_uncontended_cnt = 0; |
|
110 static int sum_waiting_hdr_waiting1_cnt = 0; |
|
111 static int sum_waiting_thr_state_blocked_cnt = 0; |
|
112 static String thread_state_line = null; |
|
113 static boolean verbose = false; |
|
114 static int waiting_line_match_cnt = 0; |
|
115 |
|
116 public static void main(String[] args) throws Exception { |
|
117 if (args.length != 0) { |
|
118 int arg_i = 0; |
|
119 if (args[arg_i].equals("-v")) { |
|
120 verbose = true; |
|
121 arg_i++; |
|
122 } |
|
123 |
|
124 try { |
|
125 n_samples = Integer.parseInt(args[arg_i]); |
|
126 } catch (NumberFormatException nfe) { |
|
127 System.err.println(nfe); |
|
128 usage(); |
|
129 } |
|
130 } |
|
131 |
|
132 Runnable runnable = new Runnable() { |
|
133 public void run() { |
|
134 synchronized (barrier) { |
|
135 // let the main thread know we're running |
|
136 barrier_cnt++; |
|
137 barrier.notify(); |
|
138 } |
|
139 while (!done) { |
|
140 synchronized (this) { } |
|
141 } |
|
142 } |
|
143 }; |
|
144 Thread[] thread_list = new Thread[2]; |
|
145 thread_list[0] = new Thread(runnable, "ContendingThread-1"); |
|
146 thread_list[1] = new Thread(runnable, "ContendingThread-2"); |
|
147 synchronized (barrier) { |
|
148 thread_list[0].start(); |
|
149 thread_list[1].start(); |
|
150 |
|
151 // Wait until the contending threads are running so that |
|
152 // we don't sample any thread init states. |
|
153 while (barrier_cnt < 2) { |
|
154 barrier.wait(); |
|
155 } |
|
156 } |
|
157 |
|
158 doSamples(); |
|
159 |
|
160 done = true; |
|
161 |
|
162 thread_list[0].join(); |
|
163 thread_list[1].join(); |
|
164 |
|
165 if (error_cnt == 0) { |
|
166 System.out.println("Test PASSED."); |
|
167 } else { |
|
168 System.out.println("Test FAILED."); |
|
169 throw new AssertionError("error_cnt=" + error_cnt); |
|
170 } |
|
171 } |
|
172 |
|
173 // Reached a blank line which is the end of the |
|
174 // stack trace without matching either LOCK_PATTERN |
|
175 // or WAITING_PATTERN. Rare, but it's not an error. |
|
176 // |
|
177 // Example: |
|
178 // "ContendingThread-1" #21 prio=5 os_prio=64 tid=0x00000000007b9000 nid=0x2f runnable [0xfffffd7fc1111000] |
|
179 // java.lang.Thread.State: RUNNABLE |
|
180 // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:140) |
|
181 // at java.lang.Thread.run(Thread.java:745) |
|
182 // |
|
183 static boolean checkBlankLine(String line) { |
|
184 if (line.length() == 0) { |
|
185 blank_line_match_cnt++; |
|
186 have_header_line = false; |
|
187 have_thread_state_line = false; |
|
188 return true; |
|
189 } |
|
190 |
|
191 return false; |
|
192 } |
|
193 |
|
194 // Process the locked line here if we found one. |
|
195 // |
|
196 // Example 1: |
|
197 // "ContendingThread-1" #21 prio=5 os_prio=64 tid=0x00000000007b9000 nid=0x2f runnable [0xfffffd7fc1111000] |
|
198 // java.lang.Thread.State: RUNNABLE |
|
199 // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:140) |
|
200 // - locked <0xfffffd7e6a2912f8> (a TestThreadDumpMonitorContention$1) |
|
201 // at java.lang.Thread.run(Thread.java:745) |
|
202 // |
|
203 // Example 2: |
|
204 // "ContendingThread-1" #21 prio=5 os_prio=64 tid=0x00000000007b9000 nid=0x2f waiting for monitor entry [0xfffffd7fc1111000] |
|
205 // java.lang.Thread.State: BLOCKED (on object monitor) |
|
206 // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:140) |
|
207 // - locked <0xfffffd7e6a2912f8> (a TestThreadDumpMonitorContention$1) |
|
208 // at java.lang.Thread.run(Thread.java:745) |
|
209 // |
|
210 // Example 3: |
|
211 // "ContendingThread-2" #24 prio=5 os_prio=64 tid=0x0000000000ec8800 nid=0x31 waiting on condition [0xfffffd7bbfffe000] |
|
212 // java.lang.Thread.State: RUNNABLE |
|
213 // JavaThread state: _thread_blocked |
|
214 // Thread: 0x0000000000ec8800 [0x31] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0 |
|
215 // JavaThread state: _thread_blocked |
|
216 // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:140) |
|
217 // - locked <0xfffffd7e6d03eb28> (a TestThreadDumpMonitorContention$1) |
|
218 // at java.lang.Thread.run(Thread.java:745) |
|
219 // |
|
220 static boolean checkLockedLine(String line) { |
|
221 Matcher matcher = LOCK_PATTERN.matcher(line); |
|
222 if (matcher.matches()) { |
|
223 if (verbose) { |
|
224 System.out.println("locked_line='" + line + "'"); |
|
225 } |
|
226 locked_match_list[locked_line_match_cnt] = new String(line); |
|
227 locked_line_match_cnt++; |
|
228 |
|
229 matcher = HEADER_RUNNABLE_PATTERN.matcher(header_line); |
|
230 if (matcher.matches()) { |
|
231 sum_locked_hdr_runnable_cnt++; |
|
232 } else { |
|
233 // It's strange, but a locked line can also |
|
234 // match the HEADER_WAITING_PATTERN{1,2}. |
|
235 matcher = HEADER_WAITING_PATTERN1.matcher(header_line); |
|
236 if (matcher.matches()) { |
|
237 sum_locked_hdr_waiting1_cnt++; |
|
238 } else { |
|
239 matcher = HEADER_WAITING_PATTERN2.matcher(header_line); |
|
240 if (matcher.matches()) { |
|
241 sum_locked_hdr_waiting2_cnt++; |
|
242 } else { |
|
243 System.err.println(); |
|
244 System.err.println("ERROR: header line does " + |
|
245 "not match runnable or waiting patterns."); |
|
246 System.err.println("ERROR: header_line='" + |
|
247 header_line + "'"); |
|
248 System.err.println("ERROR: locked_line='" + line + |
|
249 "'"); |
|
250 error_cnt++; |
|
251 } |
|
252 } |
|
253 } |
|
254 |
|
255 matcher = THREAD_STATE_RUNNABLE_PATTERN.matcher(thread_state_line); |
|
256 if (matcher.matches()) { |
|
257 sum_locked_thr_state_runnable_cnt++; |
|
258 } else { |
|
259 // It's strange, but a locked line can also |
|
260 // match the THREAD_STATE_BLOCKED_PATTERN. |
|
261 matcher = THREAD_STATE_BLOCKED_PATTERN.matcher( |
|
262 thread_state_line); |
|
263 if (matcher.matches()) { |
|
264 sum_locked_thr_state_blocked_cnt++; |
|
265 } else { |
|
266 System.err.println(); |
|
267 System.err.println("ERROR: thread state line does not " + |
|
268 "match runnable or waiting patterns."); |
|
269 System.err.println("ERROR: " + "thread_state_line='" + |
|
270 thread_state_line + "'"); |
|
271 System.err.println("ERROR: locked_line='" + line + "'"); |
|
272 error_cnt++; |
|
273 } |
|
274 } |
|
275 |
|
276 // Have everything we need from this thread stack |
|
277 // that matches the LOCK_PATTERN. |
|
278 have_header_line = false; |
|
279 have_thread_state_line = false; |
|
280 return true; |
|
281 } |
|
282 |
|
283 return false; |
|
284 } |
|
285 |
|
286 // Process the waiting line here if we found one. |
|
287 // |
|
288 // Example: |
|
289 // "ContendingThread-2" #22 prio=5 os_prio=64 tid=0x00000000007b9800 nid=0x30 waiting for monitor entry [0xfffffd7fc1010000] |
|
290 // java.lang.Thread.State: BLOCKED (on object monitor) |
|
291 // at TestThreadDumpMonitorContention$1.run(TestThreadDumpMonitorContention.java:140) |
|
292 // - waiting to lock <0xfffffd7e6a2912f8> (a TestThreadDumpMonitorContention$1) |
|
293 // at java.lang.Thread.run(Thread.java:745) |
|
294 // |
|
295 static boolean checkWaitingLine(String line) { |
|
296 Matcher matcher = WAITING_PATTERN.matcher(line); |
|
297 if (matcher.matches()) { |
|
298 waiting_line_match_cnt++; |
|
299 if (verbose) { |
|
300 System.out.println("waiting_line='" + line + "'"); |
|
301 } |
|
302 |
|
303 matcher = HEADER_WAITING_PATTERN1.matcher(header_line); |
|
304 if (matcher.matches()) { |
|
305 sum_waiting_hdr_waiting1_cnt++; |
|
306 } else { |
|
307 System.err.println(); |
|
308 System.err.println("ERROR: header line does " + |
|
309 "not match a waiting pattern."); |
|
310 System.err.println("ERROR: header_line='" + header_line + "'"); |
|
311 System.err.println("ERROR: waiting_line='" + line + "'"); |
|
312 error_cnt++; |
|
313 } |
|
314 |
|
315 matcher = THREAD_STATE_BLOCKED_PATTERN.matcher(thread_state_line); |
|
316 if (matcher.matches()) { |
|
317 sum_waiting_thr_state_blocked_cnt++; |
|
318 } else { |
|
319 System.err.println(); |
|
320 System.err.println("ERROR: thread state line " + |
|
321 "does not match a waiting pattern."); |
|
322 System.err.println("ERROR: thread_state_line='" + |
|
323 thread_state_line + "'"); |
|
324 System.err.println("ERROR: waiting_line='" + line + "'"); |
|
325 error_cnt++; |
|
326 } |
|
327 |
|
328 // Have everything we need from this thread stack |
|
329 // that matches the WAITING_PATTERN. |
|
330 have_header_line = false; |
|
331 have_thread_state_line = false; |
|
332 return true; |
|
333 } |
|
334 |
|
335 return false; |
|
336 } |
|
337 |
|
338 static void doSamples() throws Exception { |
|
339 for (int count = 0; count < n_samples; count++) { |
|
340 blank_line_match_cnt = 0; |
|
341 header_prefix_match_cnt = 0; |
|
342 locked_line_match_cnt = 0; |
|
343 waiting_line_match_cnt = 0; |
|
344 // verbose mode or an error has a lot of output so add more space |
|
345 if (verbose || error_cnt > 0) System.out.println(); |
|
346 System.out.println("Sample #" + count); |
|
347 |
|
348 // We don't use the ProcessTools, OutputBuffer or |
|
349 // OutputAnalyzer classes from the testlibrary because |
|
350 // we have a complicated multi-line parse to perform |
|
351 // on a narrow subset of the JSTACK output. |
|
352 // |
|
353 // - we only care about stack traces that match |
|
354 // HEADER_PREFIX_PATTERN; only two should match |
|
355 // - we care about at most three lines from each stack trace |
|
356 // - if both stack traces match LOCKED_PATTERN, then that's |
|
357 // a failure and we report it |
|
358 // - for a stack trace that matches LOCKED_PATTERN, we verify: |
|
359 // - the header line matches HEADER_RUNNABLE_PATTERN |
|
360 // or HEADER_WAITING_PATTERN{1,2} |
|
361 // - the thread state line matches THREAD_STATE_BLOCKED_PATTERN |
|
362 // or THREAD_STATE_RUNNABLE_PATTERN |
|
363 // - we report any mismatches as failures |
|
364 // - for a stack trace that matches WAITING_PATTERN, we verify: |
|
365 // - the header line matches HEADER_WAITING_PATTERN1 |
|
366 // - the thread state line matches THREAD_STATE_BLOCKED_PATTERN |
|
367 // - we report any mismatches as failures |
|
368 // - the stack traces that match HEADER_PREFIX_PATTERN may |
|
369 // not match either LOCKED_PATTERN or WAITING_PATTERN |
|
370 // because we might observe the thread outside of |
|
371 // monitor operations; this is not considered a failure |
|
372 // |
|
373 // When we do observe LOCKED_PATTERN or WAITING_PATTERN, |
|
374 // then we are checking the header and thread state patterns |
|
375 // that occurred earlier in the current stack trace that |
|
376 // matched HEADER_PREFIX_PATTERN. We don't use data from |
|
377 // stack traces that don't match HEADER_PREFIX_PATTERN and |
|
378 // we don't mix data between the two stack traces that do |
|
379 // match HEADER_PREFIX_PATTERN. |
|
380 // |
|
381 Process process = new ProcessBuilder(JSTACK, PID) |
|
382 .redirectErrorStream(true).start(); |
|
383 |
|
384 BufferedReader reader = new BufferedReader(new InputStreamReader( |
|
385 process.getInputStream())); |
|
386 String line; |
|
387 while ((line = reader.readLine()) != null) { |
|
388 Matcher matcher = null; |
|
389 |
|
390 // process the header line here |
|
391 if (!have_header_line) { |
|
392 matcher = HEADER_PREFIX_PATTERN.matcher(line); |
|
393 if (matcher.matches()) { |
|
394 header_prefix_match_cnt++; |
|
395 if (verbose) { |
|
396 System.out.println(); |
|
397 System.out.println("header='" + line + "'"); |
|
398 } |
|
399 header_line = new String(line); |
|
400 have_header_line = true; |
|
401 continue; |
|
402 } |
|
403 continue; // skip until have a header line |
|
404 } |
|
405 |
|
406 // process the thread state line here |
|
407 if (!have_thread_state_line) { |
|
408 matcher = THREAD_STATE_PREFIX_PATTERN.matcher(line); |
|
409 if (matcher.matches()) { |
|
410 if (verbose) { |
|
411 System.out.println("thread_state='" + line + "'"); |
|
412 } |
|
413 thread_state_line = new String(line); |
|
414 have_thread_state_line = true; |
|
415 continue; |
|
416 } |
|
417 continue; // skip until we have a thread state line |
|
418 } |
|
419 |
|
420 // process the locked line here if we find one |
|
421 if (checkLockedLine(line)) { |
|
422 continue; |
|
423 } |
|
424 |
|
425 // process the waiting line here if we find one |
|
426 if (checkWaitingLine(line)) { |
|
427 continue; |
|
428 } |
|
429 |
|
430 // process the blank line here if we find one |
|
431 if (checkBlankLine(line)) { |
|
432 continue; |
|
433 } |
|
434 } |
|
435 process.waitFor(); |
|
436 |
|
437 if (header_prefix_match_cnt != 2) { |
|
438 System.err.println(); |
|
439 System.err.println("ERROR: should match exactly two headers."); |
|
440 System.err.println("ERROR: header_prefix_match_cnt=" + |
|
441 header_prefix_match_cnt); |
|
442 error_cnt++; |
|
443 } |
|
444 |
|
445 if (locked_line_match_cnt == 2) { |
|
446 if (locked_match_list[0].equals(locked_match_list[1])) { |
|
447 System.err.println(); |
|
448 System.err.println("ERROR: matching lock lines:"); |
|
449 System.err.println("ERROR: line[0]'" + |
|
450 locked_match_list[0] + "'"); |
|
451 System.err.println("ERROR: line[1]'" + |
|
452 locked_match_list[1] + "'"); |
|
453 error_cnt++; |
|
454 } |
|
455 } |
|
456 |
|
457 if (locked_line_match_cnt == 1) { |
|
458 // one thread has the lock |
|
459 if (waiting_line_match_cnt == 1) { |
|
460 // and the other contended for it |
|
461 sum_contended_cnt++; |
|
462 } else { |
|
463 // and the other is just running |
|
464 sum_uncontended_cnt++; |
|
465 } |
|
466 } else if (waiting_line_match_cnt == 1) { |
|
467 // one thread is waiting |
|
468 sum_one_waiting_cnt++; |
|
469 } else if (waiting_line_match_cnt == 2) { |
|
470 // both threads are waiting |
|
471 sum_both_waiting_cnt++; |
|
472 } else { |
|
473 // both threads are running |
|
474 sum_both_running_cnt++; |
|
475 } |
|
476 |
|
477 // slight delay between jstack launches |
|
478 Thread.sleep(500); |
|
479 } |
|
480 |
|
481 if (error_cnt != 0) { |
|
482 // skip summary info since there were errors |
|
483 return; |
|
484 } |
|
485 |
|
486 System.out.println("INFO: Summary for all samples:"); |
|
487 System.out.println("INFO: both_running_cnt=" + sum_both_running_cnt); |
|
488 System.out.println("INFO: both_waiting_cnt=" + sum_both_waiting_cnt); |
|
489 System.out.println("INFO: contended_cnt=" + sum_contended_cnt); |
|
490 System.out.println("INFO: one_waiting_cnt=" + sum_one_waiting_cnt); |
|
491 System.out.println("INFO: uncontended_cnt=" + sum_uncontended_cnt); |
|
492 System.out.println("INFO: locked_hdr_runnable_cnt=" + |
|
493 sum_locked_hdr_runnable_cnt); |
|
494 System.out.println("INFO: locked_hdr_waiting1_cnt=" + |
|
495 sum_locked_hdr_waiting1_cnt); |
|
496 System.out.println("INFO: locked_hdr_waiting2_cnt=" + |
|
497 sum_locked_hdr_waiting2_cnt); |
|
498 System.out.println("INFO: locked_thr_state_blocked_cnt=" + |
|
499 sum_locked_thr_state_blocked_cnt); |
|
500 System.out.println("INFO: locked_thr_state_runnable_cnt=" + |
|
501 sum_locked_thr_state_runnable_cnt); |
|
502 System.out.println("INFO: waiting_hdr_waiting1_cnt=" + |
|
503 sum_waiting_hdr_waiting1_cnt); |
|
504 System.out.println("INFO: waiting_thr_state_blocked_cnt=" + |
|
505 sum_waiting_thr_state_blocked_cnt); |
|
506 |
|
507 if (sum_contended_cnt == 0) { |
|
508 System.err.println("WARNING: the primary scenario for 8036823" + |
|
509 " has not been exercised by this test run."); |
|
510 } |
|
511 } |
|
512 |
|
513 // This helper relies on RuntimeMXBean.getName() returning a string |
|
514 // that looks like this: 5436@mt-haku |
|
515 // |
|
516 // The testlibrary has tryFindJvmPid(), but that uses a separate |
|
517 // process which is much more expensive for finding out your own PID. |
|
518 // |
|
519 static String getPid() { |
|
520 RuntimeMXBean runtimebean = ManagementFactory.getRuntimeMXBean(); |
|
521 String vmname = runtimebean.getName(); |
|
522 int i = vmname.indexOf('@'); |
|
523 if (i != -1) { |
|
524 vmname = vmname.substring(0, i); |
|
525 } |
|
526 return vmname; |
|
527 } |
|
528 |
|
529 static void usage() { |
|
530 System.err.println("Usage: " + |
|
531 "java TestThreadDumpMonitorContention [-v] [n_samples]"); |
|
532 System.exit(1); |
|
533 } |
|
534 } |