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