8324066: "clhsdb jstack" should not by default scan for j.u.c locks because it can be very slow
Reviewed-by: kevinw, amenkov
This commit is contained in:
parent
6b09a79d64
commit
192349eee4
@ -53,7 +53,7 @@ Available commands:
|
||||
intConstant [ name [ value ] ] <font color="red">print out hotspot integer constant(s)</font>
|
||||
jdis address <font color="red">show bytecode disassembly of a given Method*</font>
|
||||
jhisto <font color="red">show Java heap histogram</font>
|
||||
jstack [-v] <font color="red">show Java stack trace of all Java threads. -v is verbose mode</font>
|
||||
jstack [-v] [-l] <font color="red">show Java stack trace of all Java threads. -v is verbose mode. -l includes info on owned java.util.concurrent locks.</font>
|
||||
livenmethods <font color="red">show all live nmethods</font>
|
||||
longConstant [ name [ value ] ] <font color="red">print out hotspot long constant(s)s</font>
|
||||
mem [ -v ] { address[/count] | address,address } <font color="red">show contents of memory range. -v adds "findpc" info for addresses</font>
|
||||
@ -62,7 +62,7 @@ Available commands:
|
||||
printas type expression <font color="red">print given address as given HotSpot type. eg. print JavaThread <address></font>
|
||||
printmdo -a | expression <font color="red">print method data oop</font>
|
||||
printstatics [ type ] <font color="red">print static fields of given HotSpot type (or all types if none specified)</font>
|
||||
pstack [-v] <font color="red">show mixed mode stack trace for all Java, non-Java threads. -v is verbose mode</font>
|
||||
pstack [-v] [-l] <font color="red">show mixed mode stack trace for all Java, non-Java threads. -v is verbose mode. -l includes info on owned java.util.concurrent locks.</font>
|
||||
quit <font color="red">quit CLHSDB tool</font>
|
||||
reattach <font color="red">detach and re-attach SA to current target</font>
|
||||
revptrs <font color="red">find liveness of oops</font>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1143,13 +1143,22 @@ public class CommandProcessor {
|
||||
histo.run(out, err);
|
||||
}
|
||||
},
|
||||
new Command("jstack", "jstack [-v]", false) {
|
||||
new Command("jstack", "jstack [-v] [-l]", false) {
|
||||
public void doit(Tokens t) {
|
||||
boolean verbose = false;
|
||||
if (t.countTokens() > 0 && t.nextToken().equals("-v")) {
|
||||
verbose = true;
|
||||
boolean concurrentLocks = false;
|
||||
while (t.countTokens() > 0) {
|
||||
String arg = t.nextToken();
|
||||
if (arg.equals("-v")) {
|
||||
verbose = true;
|
||||
} else if (arg.equals("-l")) {
|
||||
concurrentLocks = true;
|
||||
} else {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
StackTrace jstack = new StackTrace(verbose, true);
|
||||
StackTrace jstack = new StackTrace(verbose, concurrentLocks);
|
||||
jstack.run(out);
|
||||
}
|
||||
},
|
||||
@ -1201,13 +1210,22 @@ public class CommandProcessor {
|
||||
pmap.run(out, debugger.getAgent().getDebugger());
|
||||
}
|
||||
},
|
||||
new Command("pstack", "pstack [-v]", false) {
|
||||
new Command("pstack", "pstack [-v] [-l]", false) {
|
||||
public void doit(Tokens t) {
|
||||
boolean verbose = false;
|
||||
if (t.countTokens() > 0 && t.nextToken().equals("-v")) {
|
||||
verbose = true;
|
||||
boolean concurrentLocks = false;
|
||||
while (t.countTokens() > 0) {
|
||||
String arg = t.nextToken();
|
||||
if (arg.equals("-v")) {
|
||||
verbose = true;
|
||||
} else if (arg.equals("-l")) {
|
||||
concurrentLocks = true;
|
||||
} else {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
PStack pstack = new PStack(verbose, true, debugger.getAgent());
|
||||
PStack pstack = new PStack(verbose, concurrentLocks, debugger.getAgent());
|
||||
pstack.run(out, debugger.getAgent().getDebugger());
|
||||
}
|
||||
},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -31,12 +31,14 @@ import sun.jvm.hotspot.oops.*;
|
||||
|
||||
public class ConcurrentLocksPrinter {
|
||||
private final Map<JavaThread, List<Oop>> locksMap = new HashMap<>();
|
||||
private PrintStream tty;
|
||||
|
||||
public ConcurrentLocksPrinter() {
|
||||
public ConcurrentLocksPrinter(PrintStream tty) {
|
||||
this.tty = tty;
|
||||
fillLocks();
|
||||
}
|
||||
|
||||
public void print(JavaThread jthread, PrintStream tty) {
|
||||
public void print(JavaThread jthread) {
|
||||
List<Oop> locks = locksMap.get(jthread);
|
||||
tty.println("Locked ownable synchronizers:");
|
||||
if (locks == null || locks.isEmpty()) {
|
||||
@ -66,6 +68,7 @@ public class ConcurrentLocksPrinter {
|
||||
ObjectHeap heap = vm.getObjectHeap();
|
||||
// may be not loaded at all
|
||||
if (absOwnSyncKlass != null) {
|
||||
tty.println("Finding concurrent locks. This might take a while...");
|
||||
heap.iterateObjectsOfKlass(new DefaultHeapVisitor() {
|
||||
public boolean doObj(Oop oop) {
|
||||
JavaThread thread = getOwnerThread(oop);
|
||||
@ -77,6 +80,7 @@ public class ConcurrentLocksPrinter {
|
||||
}
|
||||
|
||||
}, absOwnSyncKlass, true);
|
||||
tty.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ public class PStack extends Tool {
|
||||
// compute and cache java Vframes.
|
||||
initJFrameCache();
|
||||
if (concurrentLocks) {
|
||||
concLocksPrinter = new ConcurrentLocksPrinter();
|
||||
concLocksPrinter = new ConcurrentLocksPrinter(out);
|
||||
}
|
||||
// print Java level deadlocks
|
||||
try {
|
||||
@ -192,7 +192,7 @@ public class PStack extends Tool {
|
||||
if (concurrentLocks) {
|
||||
JavaThread jthread = proxyToThread.get(th);
|
||||
if (jthread != null) {
|
||||
concLocksPrinter.print(jthread, out);
|
||||
concLocksPrinter.print(jthread);
|
||||
}
|
||||
}
|
||||
} // for threads
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -68,7 +68,7 @@ public class StackTrace extends Tool {
|
||||
try {
|
||||
ConcurrentLocksPrinter concLocksPrinter = null;
|
||||
if (concurrentLocks) {
|
||||
concLocksPrinter = new ConcurrentLocksPrinter();
|
||||
concLocksPrinter = new ConcurrentLocksPrinter(tty);
|
||||
}
|
||||
Threads threads = VM.getVM().getThreads();
|
||||
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
|
||||
@ -123,9 +123,9 @@ public class StackTrace extends Tool {
|
||||
}
|
||||
tty.println();
|
||||
if (concurrentLocks) {
|
||||
concLocksPrinter.print(cur, tty);
|
||||
concLocksPrinter.print(cur);
|
||||
tty.println();
|
||||
}
|
||||
tty.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -51,6 +51,7 @@ serviceability/sa/ClhsdbJdis.java 8307393 generic-
|
||||
serviceability/sa/ClhsdbJhisto.java 8307393 generic-all
|
||||
serviceability/sa/ClhsdbJstack.java#id0 8307393 generic-all
|
||||
serviceability/sa/ClhsdbJstack.java#id1 8307393 generic-all
|
||||
serviceability/sa/ClhsdbJstackWithConcurrentLock.java 8307393 generic-all
|
||||
serviceability/sa/ClhsdbJstackXcompStress.java 8307393 generic-all
|
||||
serviceability/sa/ClhsdbLauncher.java 8307393 generic-all
|
||||
serviceability/sa/ClhsdbLongConstant.java 8307393 generic-all
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,6 +30,7 @@
|
||||
resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java 8276539 generic-all
|
||||
serviceability/sa/CDSJMapClstats.java 8276539 generic-all
|
||||
serviceability/sa/ClhsdbJhisto.java 8276539 generic-all
|
||||
serviceability/sa/ClhsdbJstackWithConcurrentLock.java 8276539 generic-all
|
||||
serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java 8276539 generic-all
|
||||
|
||||
serviceability/sa/ClhsdbFindPC.java#xcomp-core 8284045 generic-all
|
||||
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8324066
|
||||
* @summary Test the clhsdb 'jstack -l' command for printing concurrent lock information
|
||||
* @requires vm.hasSA
|
||||
* @library /test/lib
|
||||
* @run main/othervm ClhsdbJstackWithConcurrentLock
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
import jdk.test.lib.apps.LingeredApp;
|
||||
import jtreg.SkippedException;
|
||||
|
||||
public class ClhsdbJstackWithConcurrentLock {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("Starting the ClhsdbJstackWithConcurrentLock test");
|
||||
|
||||
LingeredApp theApp = null;
|
||||
try {
|
||||
ClhsdbLauncher test = new ClhsdbLauncher();
|
||||
|
||||
theApp = new LingeredAppWithConcurrentLock();
|
||||
// Use a small heap so the scan is quick.
|
||||
LingeredApp.startApp(theApp, "-Xmx4m");
|
||||
System.out.println("Started LingeredApp with pid " + theApp.getPid());
|
||||
|
||||
// Run the 'jstack -l' command to get the stack and have java.util.concurrent
|
||||
// lock information included.
|
||||
List<String> cmds = List.of("jstack -l");
|
||||
String jstackOutput = test.run(theApp.getPid(), cmds, null, null);
|
||||
|
||||
// We are looking for:
|
||||
// Locked ownable synchronizers:
|
||||
// - <0x00000000ffc2ed70>, (a java/util/concurrent/locks/ReentrantLock$NonfairSync)
|
||||
// We want to fetch the address from this line.
|
||||
String key = ", (a java/util/concurrent/locks/ReentrantLock$NonfairSync)";
|
||||
String[] lines = jstackOutput.split("\\R");
|
||||
String addressString = null;
|
||||
for (String line : lines) {
|
||||
if (line.contains(key)) {
|
||||
String[] words = line.split("[, ]");
|
||||
for (String word : words) {
|
||||
word = word.replace("<", "").replace(">", "");
|
||||
if (word.startsWith("0x")) {
|
||||
addressString = word;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (addressString != null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (addressString == null) {
|
||||
throw new RuntimeException("Token '" + key + "' not found in jstack output");
|
||||
}
|
||||
|
||||
// We are looking for the following java frame:
|
||||
// - jdk.internal.misc.Unsafe.park(boolean, long)...
|
||||
// - parking to wait for <0x00000000ffc2ed70> (a java/util/concurrent/locks/ReentrantLock$NonfairSync)
|
||||
// Note the address matches the one we found above.
|
||||
key = "- parking to wait for <" + addressString +
|
||||
"> (a java/util/concurrent/locks/ReentrantLock$NonfairSync)";
|
||||
boolean found = false;
|
||||
for (String line : lines) {
|
||||
if (line.contains(key)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
throw new RuntimeException("Token '" + key + "' not found in jstack output");
|
||||
}
|
||||
} catch (SkippedException e) {
|
||||
throw e;
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException("Test ERROR " + ex, ex);
|
||||
} finally {
|
||||
LingeredApp.stopApp(theApp);
|
||||
System.out.println("OUTPUT: " + theApp.getOutput());
|
||||
}
|
||||
System.out.println("Test PASSED");
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.test.lib.apps.LingeredApp;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
|
||||
public class LingeredAppWithConcurrentLock extends LingeredApp {
|
||||
|
||||
private static final Lock lock = new ReentrantLock();
|
||||
|
||||
public static void lockMethod(Lock lock) {
|
||||
lock.lock();
|
||||
synchronized (lock) {
|
||||
try {
|
||||
Thread.sleep(300000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
Thread classLock1 = new Thread(() -> lockMethod(lock));
|
||||
Thread classLock2 = new Thread(() -> lockMethod(lock));
|
||||
Thread classLock3 = new Thread(() -> lockMethod(lock));
|
||||
|
||||
classLock1.start();
|
||||
classLock2.start();
|
||||
classLock3.start();
|
||||
|
||||
// Wait until all threads have reached their blocked or timed wait state
|
||||
while ((classLock1.getState() != Thread.State.WAITING &&
|
||||
classLock1.getState() != Thread.State.TIMED_WAITING) ||
|
||||
(classLock2.getState() != Thread.State.WAITING &&
|
||||
classLock2.getState() != Thread.State.TIMED_WAITING) ||
|
||||
(classLock3.getState() != Thread.State.WAITING &&
|
||||
classLock3.getState() != Thread.State.TIMED_WAITING)) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
System.out.println("classLock1 state: " + classLock1.getState());
|
||||
System.out.println("classLock2 state: " + classLock2.getState());
|
||||
System.out.println("classLock3 state: " + classLock3.getState());
|
||||
|
||||
LingeredApp.main(args);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -79,7 +79,7 @@ import jdk.test.lib.util.CoreUtils;
|
||||
*
|
||||
* After app termination (stopApp/waitAppTermination) its output is available
|
||||
*
|
||||
* output = a.getAppOutput();
|
||||
* output = a.getOutput();
|
||||
*
|
||||
*/
|
||||
public class LingeredApp {
|
||||
|
Loading…
Reference in New Issue
Block a user