Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java
41161 views
/*1* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324package sun.jvm.hotspot.tools;2526import java.io.*;27import java.util.*;28import sun.jvm.hotspot.*;29import sun.jvm.hotspot.code.*;30import sun.jvm.hotspot.interpreter.*;31import sun.jvm.hotspot.debugger.*;32import sun.jvm.hotspot.debugger.cdbg.*;33import sun.jvm.hotspot.debugger.remote.*;34import sun.jvm.hotspot.oops.*;35import sun.jvm.hotspot.runtime.*;36import sun.jvm.hotspot.utilities.PlatformInfo;3738public class PStack extends Tool {39// in non-verbose mode, Method*s are not printed in java frames40public PStack(boolean v, boolean concurrentLocks, HotSpotAgent agent) {41super(agent);42this.verbose = v;43this.concurrentLocks = concurrentLocks;44}4546public PStack(boolean v, boolean concurrentLocks) {47this(v, concurrentLocks, null);48}4950public PStack() {51this(true, true, null);52}5354public PStack(JVMDebugger d) {55super(d);56}5758public void run() {59run(System.out);60}6162public void run(PrintStream out) {63Debugger dbg = getAgent().getDebugger();64run(out, dbg);65}6667public void run(PrintStream out, Debugger dbg) {68CDebugger cdbg = dbg.getCDebugger();69if (cdbg != null) {70ConcurrentLocksPrinter concLocksPrinter = null;71// compute and cache java Vframes.72initJFrameCache();73if (concurrentLocks) {74concLocksPrinter = new ConcurrentLocksPrinter();75}76// print Java level deadlocks77try {78DeadlockDetector.print(out);79} catch (Exception exp) {80out.println("can't print deadlock information: " + exp.getMessage());81}8283List<ThreadProxy> l = cdbg.getThreadList();84if (l.isEmpty() && PlatformInfo.getOS().equals("darwin")) {85// If the list is empty, we assume we attached to a process, and on OSX we can only86// get the native thread list for core files.87out.println("Not available for Mac OS X processes");88return;89}90final boolean cdbgCanDemangle = cdbg.canDemangle();91String fillerForAddress = " ".repeat(2 + 2 * (int) VM.getVM().getAddressSize()) + "\t";92for (Iterator<ThreadProxy> itr = l.iterator() ; itr.hasNext();) {93ThreadProxy th = itr.next();94try {95CFrame f = cdbg.topFrameForThread(th);96out.print("----------------- ");97out.print(th);98out.println(" -----------------");99JavaThread jthread = (JavaThread) proxyToThread.get(th);100if (jthread != null) {101jthread.printThreadInfoOn(out);102}103while (f != null) {104ClosestSymbol sym = f.closestSymbolToPC();105Address pc = f.pc();106out.print(pc + "\t");107if (sym != null) {108String name = sym.getName();109if (cdbgCanDemangle) {110name = cdbg.demangle(name);111}112out.print(name);113long diff = sym.getOffset();114if (diff != 0L) {115out.print(" + 0x" + Long.toHexString(diff));116}117out.println();118} else {119// look for one or more java frames120String[] names = null;121// check interpreter frame122Interpreter interp = VM.getVM().getInterpreter();123if (interp.contains(pc)) {124names = getJavaNames(th, f.localVariableBase());125// print codelet name if we can't determine method126if (names == null || names.length == 0) {127out.print("<interpreter> ");128InterpreterCodelet ic = interp.getCodeletContaining(pc);129if (ic != null) {130String desc = ic.getDescription();131if (desc != null) out.print(desc);132}133out.println();134}135} else {136// look for known code blobs137CodeCache c = VM.getVM().getCodeCache();138if (c.contains(pc)) {139CodeBlob cb = c.findBlobUnsafe(pc);140if (cb.isNMethod()) {141if (cb.isNativeMethod()) {142out.print(((CompiledMethod)cb).getMethod().externalNameAndSignature());143long diff = pc.minus(cb.codeBegin());144if (diff != 0L) {145out.print(" + 0x" + Long.toHexString(diff));146}147out.println(" (Native method)");148} else {149names = getJavaNames(th, f.localVariableBase());150// just print compiled code, if can't determine method151if (names == null || names.length == 0) {152out.println("<Unknown compiled code>");153}154}155} else if (cb.isBufferBlob()) {156out.println("<StubRoutines>");157} else if (cb.isRuntimeStub()) {158out.println("<RuntimeStub>");159} else if (cb.isDeoptimizationStub()) {160out.println("<DeoptimizationStub>");161} else if (cb.isUncommonTrapStub()) {162out.println("<UncommonTrap>");163} else if (cb.isExceptionStub()) {164out.println("<ExceptionStub>");165} else if (cb.isSafepointStub()) {166out.println("<SafepointStub>");167} else {168out.println("<Unknown code blob>");169}170} else {171printUnknown(out);172}173}174// print java frames, if any175if (names != null && names.length != 0) {176// print java frame(s)177for (int i = 0; i < names.length; i++) {178if (i > 0) {179out.print(fillerForAddress);180}181out.println(names[i]);182}183}184}185f = f.sender(th);186}187} catch (Exception exp) {188exp.printStackTrace();189// continue, may be we can do a better job for other threads190}191if (concurrentLocks) {192JavaThread jthread = (JavaThread) proxyToThread.get(th);193if (jthread != null) {194concLocksPrinter.print(jthread, out);195}196}197} // for threads198} else {199if (getDebugeeType() == DEBUGEE_REMOTE) {200out.print(((RemoteDebuggerClient)dbg).execCommandOnServer("pstack", Map.of("concurrentLocks", concurrentLocks)));201} else {202out.println("not yet implemented (debugger does not support CDebugger)!");203}204}205}206207public static void main(String[] args) throws Exception {208PStack t = new PStack();209t.execute(args);210}211212// -- Internals only below this point213private Map<ThreadProxy, JavaVFrame[]> jframeCache;214private Map<ThreadProxy, JavaThread> proxyToThread;215private PrintStream out;216private boolean verbose;217private boolean concurrentLocks;218219private void initJFrameCache() {220// cache frames for subsequent reference221jframeCache = new HashMap<>();222proxyToThread = new HashMap<>();223Threads threads = VM.getVM().getThreads();224for (int i = 0; i < threads.getNumberOfThreads(); i++) {225JavaThread cur = threads.getJavaThreadAt(i);226List<JavaVFrame> tmp = new ArrayList<>(10);227try {228for (JavaVFrame vf = cur.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {229tmp.add(vf);230}231} catch (Exception exp) {232// may be we may get frames for other threads, continue233// after printing stack trace.234exp.printStackTrace();235}236JavaVFrame[] jvframes = new JavaVFrame[tmp.size()];237System.arraycopy(tmp.toArray(), 0, jvframes, 0, jvframes.length);238jframeCache.put(cur.getThreadProxy(), jvframes);239proxyToThread.put(cur.getThreadProxy(), cur);240}241}242243private void printUnknown(PrintStream out) {244out.println("\t????????");245}246247private String[] getJavaNames(ThreadProxy th, Address fp) {248if (fp == null) {249return null;250}251JavaVFrame[] jvframes = (JavaVFrame[]) jframeCache.get(th);252if (jvframes == null) return null; // not a java thread253List<String> names = new ArrayList<>(10);254for (int fCount = 0; fCount < jvframes.length; fCount++) {255JavaVFrame vf = jvframes[fCount];256Frame f = vf.getFrame();257if (fp.equals(f.getFP())) {258StringBuilder sb = new StringBuilder();259Method method = vf.getMethod();260// a special char to identify java frames in output261sb.append("* ");262sb.append(method.externalNameAndSignature());263sb.append(" bci:").append(vf.getBCI());264int lineNumber = method.getLineNumberFromBCI(vf.getBCI());265if (lineNumber != -1) {266sb.append(" line:").append(lineNumber);267}268269if (verbose) {270sb.append(" Method*:").append(method.getAddress());271}272273if (vf.isCompiledFrame()) {274sb.append(" (Compiled frame");275if (vf.isDeoptimized()) {276sb.append(" [deoptimized]");277}278} else if (vf.isInterpretedFrame()) {279sb.append(" (Interpreted frame");280}281if (vf.mayBeImpreciseDbg()) {282sb.append("; information may be imprecise");283}284sb.append(")");285names.add(sb.toString());286}287}288String[] res = new String[names.size()];289System.arraycopy(names.toArray(), 0, res, 0, res.length);290return res;291}292293public void setVerbose(boolean verbose) {294this.verbose = verbose;295}296297public void setConcurrentLocks(boolean concurrentLocks) {298this.concurrentLocks = concurrentLocks;299}300}301302303