1 /* 2 * Copyright (c) 2003, 2019, 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 JavaThread jthread = (JavaThread) proxyToThread.get(th); 92 if (jthread != null) { 93 jthread.printThreadInfoOn(out); 94 } 95 while (f != null) { 96 ClosestSymbol sym = f.closestSymbolToPC(); 97 Address pc = f.pc(); 98 out.print(pc + "\t"); 99 if (sym != null) { 100 String name = sym.getName(); 101 if (cdbgCanDemangle) { 102 name = cdbg.demangle(name); 103 } 104 out.print(name); 105 long diff = sym.getOffset(); 106 if (diff != 0L) { 107 out.print(" + 0x" + Long.toHexString(diff)); 108 } 109 out.println(); 110 } else { 111 // look for one or more java frames 112 String[] names = null; 113 // check interpreter frame 114 Interpreter interp = VM.getVM().getInterpreter(); 115 if (interp.contains(pc)) { 116 names = getJavaNames(th, f.localVariableBase()); 117 // print codelet name if we can't determine method 118 if (names == null || names.length == 0) { 119 out.print("<interpreter> "); 120 InterpreterCodelet ic = interp.getCodeletContaining(pc); 121 if (ic != null) { 122 String desc = ic.getDescription(); 123 if (desc != null) out.print(desc); 124 } 125 out.println(); 126 } 127 } else { 128 // look for known code blobs 129 CodeCache c = VM.getVM().getCodeCache(); 130 if (c.contains(pc)) { 131 CodeBlob cb = c.findBlobUnsafe(pc); 132 if (cb.isNMethod()) { 133 names = getJavaNames(th, f.localVariableBase()); 134 if (cb.isNativeMethod()) { 135 out.print(((CompiledMethod)cb).getMethod().externalNameAndSignature()); 136 long diff = pc.minus(cb.codeBegin()); 137 if (diff != 0L) { 138 out.print(" + 0x" + Long.toHexString(diff)); 139 } 140 out.println(" (Native method)"); 141 } else if (names == null || names.length == 0) { 142 // just print compiled code, if can't determine method 143 out.println("<Unknown compiled code>"); 144 } 145 } else if (cb.isBufferBlob()) { 146 out.println("<StubRoutines>"); 147 } else if (cb.isRuntimeStub()) { 148 out.println("<RuntimeStub>"); 149 } else if (cb.isDeoptimizationStub()) { 150 out.println("<DeoptimizationStub>"); 151 } else if (cb.isUncommonTrapStub()) { 152 out.println("<UncommonTrap>"); 153 } else if (cb.isExceptionStub()) { 154 out.println("<ExceptionStub>"); 155 } else if (cb.isSafepointStub()) { 156 out.println("<SafepointStub>"); 157 } else { 158 out.println("<Unknown code blob>"); 159 } 160 } else { 161 printUnknown(out); 162 } 163 } 164 // print java frames, if any 165 if (names != null && names.length != 0) { 166 // print java frame(s) 167 for (int i = 0; i < names.length; i++) { 168 out.println(names[i]); 169 } 170 } 171 } 172 f = f.sender(th); 173 } 174 } catch (Exception exp) { 175 exp.printStackTrace(); 176 // continue, may be we can do a better job for other threads 177 } 178 if (concurrentLocks) { 179 JavaThread jthread = (JavaThread) proxyToThread.get(th); 180 if (jthread != null) { 181 concLocksPrinter.print(jthread, out); 182 } 183 } 184 } // for threads 185 } else { 186 if (getDebugeeType() == DEBUGEE_REMOTE) { 187 out.println("remote configuration is not yet implemented"); 188 } else { 189 out.println("not yet implemented (debugger does not support CDebugger)!"); 190 } 191 } 192 } 193 194 public static void main(String[] args) throws Exception { 195 PStack t = new PStack(); 196 t.execute(args); 197 } 198 199 // -- Internals only below this point 200 private Map jframeCache; // Map<ThreadProxy, JavaVFrame[]> 201 private Map proxyToThread; // Map<ThreadProxy, JavaThread> 202 private PrintStream out; 203 private boolean verbose; 204 private boolean concurrentLocks; 205 206 private void initJFrameCache() { 207 // cache frames for subsequent reference 208 jframeCache = new HashMap(); 209 proxyToThread = new HashMap(); 210 Threads threads = VM.getVM().getThreads(); 211 for (int i = 0; i < threads.getNumberOfThreads(); i++) { 212 JavaThread cur = threads.getJavaThreadAt(i); 213 List tmp = new ArrayList(10); 214 try { 215 for (JavaVFrame vf = cur.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) { 216 tmp.add(vf); 217 } 218 } catch (Exception exp) { 219 // may be we may get frames for other threads, continue 220 // after printing stack trace. 221 exp.printStackTrace(); 222 } 223 JavaVFrame[] jvframes = new JavaVFrame[tmp.size()]; 224 System.arraycopy(tmp.toArray(), 0, jvframes, 0, jvframes.length); 225 jframeCache.put(cur.getThreadProxy(), jvframes); 226 proxyToThread.put(cur.getThreadProxy(), cur); 227 } 228 } 229 230 private void printUnknown(PrintStream out) { 231 out.println("\t????????"); 232 } 233 234 private String[] getJavaNames(ThreadProxy th, Address fp) { 235 if (fp == null) { 236 return null; 237 } 238 JavaVFrame[] jvframes = (JavaVFrame[]) jframeCache.get(th); 239 if (jvframes == null) return null; // not a java thread 240 List names = new ArrayList(10); 241 for (int fCount = 0; fCount < jvframes.length; fCount++) { 242 JavaVFrame vf = jvframes[fCount]; 243 Frame f = vf.getFrame(); 244 if (fp.equals(f.getFP())) { 245 StringBuffer sb = new StringBuffer(); 246 Method method = vf.getMethod(); 247 // a special char to identify java frames in output 248 sb.append("* "); 249 sb.append(method.externalNameAndSignature()); 250 sb.append(" bci:" + vf.getBCI()); 251 int lineNumber = method.getLineNumberFromBCI(vf.getBCI()); 252 if (lineNumber != -1) { 253 sb.append(" line:" + lineNumber); 254 } 255 256 if (verbose) { 257 sb.append(" Method*:" + method.getAddress()); 258 } 259 260 if (vf.isCompiledFrame()) { 261 sb.append(" (Compiled frame"); 262 if (vf.isDeoptimized()) { 263 sb.append(" [deoptimized]"); 264 } 265 } else if (vf.isInterpretedFrame()) { 266 sb.append(" (Interpreted frame"); 267 } 268 if (vf.mayBeImpreciseDbg()) { 269 sb.append("; information may be imprecise"); 270 } 271 sb.append(")"); 272 names.add(sb.toString()); 273 } 274 } 275 String[] res = new String[names.size()]; 276 System.arraycopy(names.toArray(), 0, res, 0, res.length); 277 return res; 278 } 279 } --- EOF ---