src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java
changeset 47216 71c04702a3d5
parent 46636 26b8de0359a0
child 54955 46409371a691
--- /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;
+   }
+}