1 /* 2 * Copyright 2003-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.tools; 26 27 import java.io.*; 28 import java.util.*; 29 import sun.jvm.hotspot.code.*; 30 import sun.jvm.hotspot.interpreter.*; 31 import sun.jvm.hotspot.debugger.*; 32 import sun.jvm.hotspot.debugger.cdbg.*; 33 import sun.jvm.hotspot.oops.*; 34 import sun.jvm.hotspot.runtime.*; 35 36 public class PStack extends Tool { 37 // in non-verbose mode, methodOops are not printed in java frames 38 public PStack(boolean v, boolean concurrentLocks) { 39 this.verbose = v; 40 this.concurrentLocks = concurrentLocks; 41 } 42 43 public PStack() { 44 this(true, true); 45 } 46 47 public void run() { 48 run(System.out); 49 } 50 51 public void run(PrintStream out) { 52 Debugger dbg = getAgent().getDebugger(); 53 run(out, dbg, getAgent().isJavaMode()); 54 } 55 56 public void run(PrintStream out, Debugger dbg) { 57 run(out, dbg, true); 58 } 59 60 private void run(PrintStream out, Debugger dbg, final boolean isJava) { 61 CDebugger cdbg = dbg.getCDebugger(); 62 if (cdbg != null) { 63 ConcurrentLocksPrinter concLocksPrinter = null; 64 if (isJava) { 65 // compute and cache java Vframes. 66 initJFrameCache(); 67 if (concurrentLocks) { 68 concLocksPrinter = new ConcurrentLocksPrinter(); 69 } 70 // print Java level deadlocks 71 try { 72 DeadlockDetector.print(out); 73 } catch (Exception exp) { 74 out.println("can't print deadlock information: " + exp.getMessage()); 75 } 76 } 77 78 List l = cdbg.getThreadList(); 79 final boolean cdbgCanDemangle = cdbg.canDemangle(); 80 for (Iterator itr = l.iterator() ; itr.hasNext();) { 81 ThreadProxy th = (ThreadProxy) itr.next(); 82 try { 83 CFrame f = cdbg.topFrameForThread(th); 84 out.print("----------------- "); 85 out.print(th); 86 out.println(" -----------------"); 87 while (f != null) { 88 ClosestSymbol sym = f.closestSymbolToPC(); 89 Address pc = f.pc(); 90 out.print(pc + "\t"); 91 if (sym != null) { 92 String name = sym.getName(); 93 if (cdbgCanDemangle) { 94 name = cdbg.demangle(name); 95 } 96 out.print(name); 97 long diff = sym.getOffset(); 98 if (diff != 0L) { 99 out.print(" + 0x" + Long.toHexString(diff)); 100 } 101 out.println(); 102 } else { 103 if (isJava) { 104 // look for one or more java frames 105 String[] names = null; 106 // check interpreter frame 107 Interpreter interp = VM.getVM().getInterpreter(); 108 if (interp.contains(pc)) { 109 names = getJavaNames(th, f.localVariableBase()); 110 // print codelet name if we can't determine method 111 if (names == null || names.length == 0) { 112 out.print("<interpreter> "); 113 InterpreterCodelet ic = interp.getCodeletContaining(pc); 114 if (ic != null) { 115 String desc = ic.getDescription(); 116 if (desc != null) out.print(desc); 117 } 118 out.println(); 119 } 120 } else { 121 // look for known code blobs 122 CodeCache c = VM.getVM().getCodeCache(); 123 if (c.contains(pc)) { 124 CodeBlob cb = c.findBlobUnsafe(pc); 125 if (cb.isNMethod()) { 126 names = getJavaNames(th, f.localVariableBase()); 127 // just print compiled code, if can't determine method 128 if (names == null || names.length == 0) { 129 out.println("<Unknown compiled code>"); 130 } 131 } else if (cb.isBufferBlob()) { 132 out.println("<StubRoutines>"); 133 } else if (cb.isRuntimeStub()) { 134 out.println("<RuntimeStub>"); 135 } else if (cb.isDeoptimizationStub()) { 136 out.println("<DeoptimizationStub>"); 137 } else if (cb.isUncommonTrapStub()) { 138 out.println("<UncommonTrap>"); 139 } else if (cb.isExceptionStub()) { 140 out.println("<ExceptionStub>"); 141 } else if (cb.isSafepointStub()) { 142 out.println("<SafepointStub>"); 143 } else { 144 out.println("<Unknown code blob>"); 145 } 146 } else { 147 printUnknown(out); 148 } 149 } 150 // print java frames, if any 151 if (names != null && names.length != 0) { 152 // print java frame(s) 153 for (int i = 0; i < names.length; i++) { 154 out.println(names[i]); 155 } 156 } 157 } else { 158 printUnknown(out); 159 } 160 } 161 f = f.sender(); 162 } 163 } catch (Exception exp) { 164 exp.printStackTrace(); 165 // continue, may be we can do a better job for other threads 166 } 167 if (isJava && concurrentLocks) { 168 JavaThread jthread = (JavaThread) proxyToThread.get(th); 169 if (jthread != null) { 170 concLocksPrinter.print(jthread, out); 171 } 172 } 173 } // for threads 174 } else { 175 if (getDebugeeType() == DEBUGEE_REMOTE) { 176 out.println("remote configuration is not yet implemented"); 177 } else { 178 out.println("not yet implemented (debugger does not support CDebugger)!"); 179 } 180 } 181 } 182 183 protected boolean requiresVM() { 184 return false; 185 } 186 187 public static void main(String[] args) throws Exception { 188 PStack t = new PStack(); 189 t.start(args); 190 t.stop(); 191 } 192 193 // -- Internals only below this point 194 private Map jframeCache; // Map<ThreadProxy, JavaVFrame[]> 195 private Map proxyToThread; // Map<ThreadProxy, JavaThread> 196 private PrintStream out; 197 private boolean verbose; 198 private boolean concurrentLocks; 199 200 private void initJFrameCache() { 201 // cache frames for subsequent reference 202 jframeCache = new HashMap(); 203 proxyToThread = new HashMap(); 204 Threads threads = VM.getVM().getThreads(); 205 for (JavaThread cur = threads.first(); cur != null; cur = cur.next()) { 206 List tmp = new ArrayList(10); 207 try { 208 for (JavaVFrame vf = cur.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) { 209 tmp.add(vf); 210 } 211 } catch (Exception exp) { 212 // may be we may get frames for other threads, continue 213 // after printing stack trace. 214 exp.printStackTrace(); 215 } 216 JavaVFrame[] jvframes = new JavaVFrame[tmp.size()]; 217 System.arraycopy(tmp.toArray(), 0, jvframes, 0, jvframes.length); 218 jframeCache.put(cur.getThreadProxy(), jvframes); 219 proxyToThread.put(cur.getThreadProxy(), cur); 220 } 221 } 222 223 private void printUnknown(PrintStream out) { 224 out.println("????????"); 225 } 226 227 private String[] getJavaNames(ThreadProxy th, Address fp) { 228 if (fp == null) { 229 return null; 230 } 231 JavaVFrame[] jvframes = (JavaVFrame[]) jframeCache.get(th); 232 if (jvframes == null) return null; // not a java thread 233 List names = new ArrayList(10); 234 for (int fCount = 0; fCount < jvframes.length; fCount++) { 235 JavaVFrame vf = jvframes[fCount]; 236 Frame f = vf.getFrame(); 237 if (fp.equals(f.getFP())) { 238 StringBuffer sb = new StringBuffer(); 239 Method method = vf.getMethod(); 240 // a special char to identify java frames in output 241 sb.append("* "); 242 sb.append(method.externalNameAndSignature()); 243 sb.append(" bci:" + vf.getBCI()); 244 int lineNumber = method.getLineNumberFromBCI(vf.getBCI()); 245 if (lineNumber != -1) { 246 sb.append(" line:" + lineNumber); 247 } 248 249 if (verbose) { 250 sb.append(" methodOop:" + method.getHandle()); 251 } 252 253 if (vf.isCompiledFrame()) { 254 sb.append(" (Compiled frame"); 255 if (vf.isDeoptimized()) { 256 sb.append(" [deoptimized]"); 257 } 258 } else if (vf.isInterpretedFrame()) { 259 sb.append(" (Interpreted frame"); 260 } 261 if (vf.mayBeImpreciseDbg()) { 262 sb.append("; information may be imprecise"); 263 } 264 sb.append(")"); 265 names.add(sb.toString()); 266 } 267 } 268 String[] res = new String[names.size()]; 269 System.arraycopy(names.toArray(), 0, res, 0, res.length); 270 return res; 271 } 272 }