Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CLHSDB.java
41159 views
/*1* Copyright (c) 2005, 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;2526import sun.jvm.hotspot.*;27import sun.jvm.hotspot.debugger.*;2829import java.io.*;30import java.util.*;3132public class CLHSDB {3334public CLHSDB(JVMDebugger d) {35pid = -1;36execPath = null;37coreFilename = null;38debugServerName = null;39jvmDebugger = d;40}4142public static void main(String[] args) {43new CLHSDB(args).run();44}4546public void run() {47// If jvmDebugger is already set, we have been given a JVMDebugger.48// Otherwise, if pid != -1 we are supposed to attach to it.49// If execPath != null, it is the path of a jdk/bin/java50// and coreFilename is the pathname of a core file we are51// supposed to attach to.52// Finally, if debugServerName != null, we are supposed to53// connect to remote debug server.5455agent = new HotSpotAgent();5657Runtime.getRuntime().addShutdownHook(new java.lang.Thread() {58public void run() {59detachDebugger();60}61});6263if (jvmDebugger != null) {64attachDebugger(jvmDebugger);65} else if (pid != -1) {66attachDebugger(pid);67} else if (execPath != null) {68attachDebugger(execPath, coreFilename);69} else if (debugServerName != null) {70connect(debugServerName);71}727374CommandProcessor.DebuggerInterface di = new CommandProcessor.DebuggerInterface() {75public HotSpotAgent getAgent() {76return agent;77}78public boolean isAttached() {79return attached;80}81public void attach(int pid) {82attachDebugger(pid);83}84public void attach(String java, String core) {85attachDebugger(java, core);86}87public void attach(String debugServerName) {88connect(debugServerName);89}90public void detach() {91detachDebugger();92}93public void reattach() {94if (attached) {95detachDebugger();96}97if (pid != -1) {98attach(pid);99} else if (debugServerName != null) {100connect(debugServerName);101} else {102attach(execPath, coreFilename);103}104}105};106107108BufferedReader in =109new BufferedReader(new InputStreamReader(System.in));110CommandProcessor cp = new CommandProcessor(di, in, System.out, System.err);111cp.run(true);112113}114115//--------------------------------------------------------------------------------116// Internals only below this point117//118private HotSpotAgent agent;119private JVMDebugger jvmDebugger;120private boolean attached;121// These had to be made data members because they are referenced in inner classes.122private int pid;123private String execPath;124private String coreFilename;125private String debugServerName;126127private void doUsage() {128System.out.println("Usage: java CLHSDB [[pid] | [path-to-java-executable [path-to-corefile]] | help ]");129System.out.println(" pid: attach to the process whose id is 'pid'");130System.out.println(" path-to-java-executable: Debug a core file produced by this program");131System.out.println(" path-to-corefile: Debug this corefile. The default is 'core'");132System.out.println(" If no arguments are specified, you can select what to do from the GUI.\n");133HotSpotAgent.showUsage();134}135136private CLHSDB(String[] args) {137pid = -1;138execPath = null;139coreFilename = null;140debugServerName = null;141142switch (args.length) {143case (0):144break;145146case (1):147if (args[0].equals("help") || args[0].equals("-help")) {148doUsage();149return;150}151try {152// Attempt to attach as a PID153pid = Integer.parseInt(args[0]);154} catch (NumberFormatException e) {155// Attempt to connect to remote debug server156debugServerName = args[0];157}158break;159160case (2):161execPath = args[0];162coreFilename = args[1];163break;164165default:166System.out.println("HSDB Error: Too many options specified");167doUsage();168return;169}170}171172private void attachDebugger(JVMDebugger d) {173agent.attach(d);174attached = true;175}176177/** NOTE we are in a different thread here than either the main178thread or the Swing/AWT event handler thread, so we must be very179careful when creating or removing widgets */180private void attachDebugger(int pid) {181this.pid = pid;182try {183System.out.println("Attaching to process " + pid + ", please wait...");184185// FIXME: display exec'd debugger's output messages during this186// lengthy call187agent.attach(pid);188attached = true;189}190catch (DebuggerException e) {191final String errMsg = formatMessage(e.getMessage(), 80);192System.err.println("Unable to connect to process ID " + pid + ":\n\n" + errMsg);193agent.detach();194e.printStackTrace();195return;196}197}198199/** NOTE we are in a different thread here than either the main200thread or the Swing/AWT event handler thread, so we must be very201careful when creating or removing widgets */202private void attachDebugger(final String executablePath, final String corePath) {203// Try to open this core file204try {205System.out.println("Opening core file, please wait...");206207// FIXME: display exec'd debugger's output messages during this208// lengthy call209agent.attach(executablePath, corePath);210attached = true;211}212catch (DebuggerException e) {213final String errMsg = formatMessage(e.getMessage(), 80);214System.err.println("Unable to open core file\n" + corePath + ":\n\n" + errMsg);215agent.detach();216e.printStackTrace();217return;218}219}220221/** NOTE we are in a different thread here than either the main222thread or the Swing/AWT event handler thread, so we must be very223careful when creating or removing widgets */224private void connect(final String debugServerName) {225// Try to open this core file226try {227System.out.println("Connecting to debug server, please wait...");228agent.attach(debugServerName);229this.debugServerName = debugServerName;230attached = true;231}232catch (DebuggerException e) {233final String errMsg = formatMessage(e.getMessage(), 80);234System.err.println("Unable to connect to debug server \"" + debugServerName + "\":\n\n" + errMsg);235agent.detach();236e.printStackTrace();237return;238}239}240241private void detachDebugger() {242if (!attached) {243return;244}245agent.detach();246attached = false;247}248249private void detach() {250detachDebugger();251}252253/** Punctuates the given string with \n's where necessary to not254exceed the given number of characters per line. Strips255extraneous whitespace. */256private String formatMessage(String message, int charsPerLine) {257StringBuilder buf = new StringBuilder(message.length());258StringTokenizer tokenizer = new StringTokenizer(message);259int curLineLength = 0;260while (tokenizer.hasMoreTokens()) {261String tok = tokenizer.nextToken();262if (curLineLength + tok.length() > charsPerLine) {263buf.append('\n');264curLineLength = 0;265} else {266if (curLineLength != 0) {267buf.append(' ');268++curLineLength;269}270}271buf.append(tok);272curLineLength += tok.length();273}274return buf.toString();275}276}277278279