--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2003, 2017, 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.
+ *
+ */
+
+package sun.jvm.hotspot.tools;
+
+import java.io.*;
+import java.util.*;
+import sun.jvm.hotspot.code.*;
+import sun.jvm.hotspot.interpreter.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.cdbg.*;
+import sun.jvm.hotspot.oops.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.utilities.PlatformInfo;
+
+public class PStack extends Tool {
+ // in non-verbose mode, Method*s are not printed in java frames
+ public PStack(boolean v, boolean concurrentLocks) {
+ this.verbose = v;
+ this.concurrentLocks = concurrentLocks;
+ }
+
+ public PStack() {
+ this(true, true);
+ }
+
+ public PStack(JVMDebugger d) {
+ super(d);
+ }
+
+ public void run() {
+ run(System.out);
+ }
+
+ public void run(PrintStream out) {
+ Debugger dbg = getAgent().getDebugger();
+ run(out, dbg);
+ }
+
+ public void run(PrintStream out, Debugger dbg) {
+ if (PlatformInfo.getOS().equals("darwin")) {
+ out.println("Not available on Darwin");
+ return;
+ }
+
+ CDebugger cdbg = dbg.getCDebugger();
+ if (cdbg != null) {
+ ConcurrentLocksPrinter concLocksPrinter = null;
+ // compute and cache java Vframes.
+ initJFrameCache();
+ if (concurrentLocks) {
+ concLocksPrinter = new ConcurrentLocksPrinter();
+ }
+ // print Java level deadlocks
+ try {
+ DeadlockDetector.print(out);
+ } catch (Exception exp) {
+ out.println("can't print deadlock information: " + exp.getMessage());
+ }
+
+ List l = cdbg.getThreadList();
+ final boolean cdbgCanDemangle = cdbg.canDemangle();
+ for (Iterator itr = l.iterator() ; itr.hasNext();) {
+ ThreadProxy th = (ThreadProxy) itr.next();
+ try {
+ CFrame f = cdbg.topFrameForThread(th);
+ out.print("----------------- ");
+ out.print(th);
+ out.println(" -----------------");
+ JavaThread jthread = (JavaThread) proxyToThread.get(th);
+ if (jthread != null) {
+ jthread.printThreadInfoOn(out);
+ }
+ while (f != null) {
+ ClosestSymbol sym = f.closestSymbolToPC();
+ Address pc = f.pc();
+ out.print(pc + "\t");
+ if (sym != null) {
+ String name = sym.getName();
+ if (cdbgCanDemangle) {
+ name = cdbg.demangle(name);
+ }
+ out.print(name);
+ long diff = sym.getOffset();
+ if (diff != 0L) {
+ out.print(" + 0x" + Long.toHexString(diff));
+ }
+ out.println();
+ } else {
+ // look for one or more java frames
+ String[] names = null;
+ // check interpreter frame
+ Interpreter interp = VM.getVM().getInterpreter();
+ if (interp.contains(pc)) {
+ names = getJavaNames(th, f.localVariableBase());
+ // print codelet name if we can't determine method
+ if (names == null || names.length == 0) {
+ out.print("<interpreter> ");
+ InterpreterCodelet ic = interp.getCodeletContaining(pc);
+ if (ic != null) {
+ String desc = ic.getDescription();
+ if (desc != null) out.print(desc);
+ }
+ out.println();
+ }
+ } else {
+ // look for known code blobs
+ CodeCache c = VM.getVM().getCodeCache();
+ if (c.contains(pc)) {
+ CodeBlob cb = c.findBlobUnsafe(pc);
+ if (cb.isNMethod()) {
+ names = getJavaNames(th, f.localVariableBase());
+ // just print compiled code, if can't determine method
+ if (names == null || names.length == 0) {
+ out.println("<Unknown compiled code>");
+ }
+ } else if (cb.isBufferBlob()) {
+ out.println("<StubRoutines>");
+ } else if (cb.isRuntimeStub()) {
+ out.println("<RuntimeStub>");
+ } else if (cb.isDeoptimizationStub()) {
+ out.println("<DeoptimizationStub>");
+ } else if (cb.isUncommonTrapStub()) {
+ out.println("<UncommonTrap>");
+ } else if (cb.isExceptionStub()) {
+ out.println("<ExceptionStub>");
+ } else if (cb.isSafepointStub()) {
+ out.println("<SafepointStub>");
+ } else {
+ out.println("<Unknown code blob>");
+ }
+ } else {
+ printUnknown(out);
+ }
+ }
+ // print java frames, if any
+ if (names != null && names.length != 0) {
+ // print java frame(s)
+ for (int i = 0; i < names.length; i++) {
+ out.println(names[i]);
+ }
+ }
+ }
+ f = f.sender(th);
+ }
+ } catch (Exception exp) {
+ exp.printStackTrace();
+ // continue, may be we can do a better job for other threads
+ }
+ if (concurrentLocks) {
+ JavaThread jthread = (JavaThread) proxyToThread.get(th);
+ if (jthread != null) {
+ concLocksPrinter.print(jthread, out);
+ }
+ }
+ } // for threads
+ } else {
+ if (getDebugeeType() == DEBUGEE_REMOTE) {
+ out.println("remote configuration is not yet implemented");
+ } else {
+ out.println("not yet implemented (debugger does not support CDebugger)!");
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ PStack t = new PStack();
+ t.execute(args);
+ }
+
+ // -- Internals only below this point
+ private Map jframeCache; // Map<ThreadProxy, JavaVFrame[]>
+ private Map proxyToThread; // Map<ThreadProxy, JavaThread>
+ private PrintStream out;
+ private boolean verbose;
+ private boolean concurrentLocks;
+
+ private void initJFrameCache() {
+ // cache frames for subsequent reference
+ jframeCache = new HashMap();
+ proxyToThread = new HashMap();
+ Threads threads = VM.getVM().getThreads();
+ for (JavaThread cur = threads.first(); cur != null; cur = cur.next()) {
+ List tmp = new ArrayList(10);
+ try {
+ for (JavaVFrame vf = cur.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {
+ tmp.add(vf);
+ }
+ } catch (Exception exp) {
+ // may be we may get frames for other threads, continue
+ // after printing stack trace.
+ exp.printStackTrace();
+ }
+ JavaVFrame[] jvframes = new JavaVFrame[tmp.size()];
+ System.arraycopy(tmp.toArray(), 0, jvframes, 0, jvframes.length);
+ jframeCache.put(cur.getThreadProxy(), jvframes);
+ proxyToThread.put(cur.getThreadProxy(), cur);
+ }
+ }
+
+ private void printUnknown(PrintStream out) {
+ out.println("\t????????");
+ }
+
+ private String[] getJavaNames(ThreadProxy th, Address fp) {
+ if (fp == null) {
+ return null;
+ }
+ JavaVFrame[] jvframes = (JavaVFrame[]) jframeCache.get(th);
+ if (jvframes == null) return null; // not a java thread
+ List names = new ArrayList(10);
+ for (int fCount = 0; fCount < jvframes.length; fCount++) {
+ JavaVFrame vf = jvframes[fCount];
+ Frame f = vf.getFrame();
+ if (fp.equals(f.getFP())) {
+ StringBuffer sb = new StringBuffer();
+ Method method = vf.getMethod();
+ // a special char to identify java frames in output
+ sb.append("* ");
+ sb.append(method.externalNameAndSignature());
+ sb.append(" bci:" + vf.getBCI());
+ int lineNumber = method.getLineNumberFromBCI(vf.getBCI());
+ if (lineNumber != -1) {
+ sb.append(" line:" + lineNumber);
+ }
+
+ if (verbose) {
+ sb.append(" Method*:" + method.getAddress());
+ }
+
+ if (vf.isCompiledFrame()) {
+ sb.append(" (Compiled frame");
+ if (vf.isDeoptimized()) {
+ sb.append(" [deoptimized]");
+ }
+ } else if (vf.isInterpretedFrame()) {
+ sb.append(" (Interpreted frame");
+ }
+ if (vf.mayBeImpreciseDbg()) {
+ sb.append("; information may be imprecise");
+ }
+ sb.append(")");
+ names.add(sb.toString());
+ }
+ }
+ String[] res = new String[names.size()];
+ System.arraycopy(names.toArray(), 0, res, 0, res.length);
+ return res;
+ }
+}