diff agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children a5838065ab24
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2003-2006 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.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.*;
+
+public class PStack extends Tool {
+    // in non-verbose mode, methodOops are not printed in java frames
+   public PStack(boolean v, boolean concurrentLocks) {
+      this.verbose = v;
+      this.concurrentLocks = concurrentLocks;
+   }
+
+   public PStack() {
+      this(true, true);
+   }
+
+   public void run() {
+      run(System.out);
+   }
+
+   public void run(PrintStream out) {
+      Debugger dbg = getAgent().getDebugger();
+      run(out, dbg, getAgent().isJavaMode());
+   }
+
+   public void run(PrintStream out, Debugger dbg) {
+      run(out, dbg, true);
+   }
+
+   private void run(PrintStream out, Debugger dbg, final boolean isJava) {
+      CDebugger cdbg = dbg.getCDebugger();
+      if (cdbg != null) {
+         ConcurrentLocksPrinter concLocksPrinter = null;
+         if (isJava) {
+            // 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(" -----------------");
+               while (f != null) {
+                  ClosestSymbol sym = f.closestSymbolToPC();
+                  Address pc = f.pc();
+                  if (sym != null) {
+                     String name = sym.getName();
+                     if (cdbgCanDemangle) {
+                        name = cdbg.demangle(name);
+                     }
+                     out.print(pc + "\t" + name);
+                     long diff = sym.getOffset();
+                     if (diff != 0L) {
+                        out.print(" + 0x" + Long.toHexString(diff));
+                     }
+                     out.println();
+                  } else {
+                     if (isJava) {
+                        // 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)) {
+                              out.print(pc + "\t");
+                              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,pc);
+                           }
+                        }
+                        // 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(pc + "\t" + names[i]);
+                           }
+                        }
+                     } else {
+                        printUnknown(out,pc);
+                     }
+                  }
+                  f = f.sender();
+               }
+            } catch (Exception exp) {
+               exp.printStackTrace();
+               // continue, may be we can do a better job for other threads
+            }
+            if (isJava && 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)!");
+          }
+      }
+   }
+
+   protected boolean requiresVM() {
+      return false;
+   }
+
+   public static void main(String[] args) throws Exception {
+      PStack t = new PStack();
+      t.start(args);
+      t.stop();
+   }
+
+   // -- 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, Address pc) {
+      out.println(pc + "\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(" methodOop:" + method.getHandle());
+            }
+
+            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;
+   }
+}