Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/Tool.java
41161 views
/*1* Copyright (c) 2002, 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.PrintStream;2728import sun.jvm.hotspot.HotSpotAgent;29import sun.jvm.hotspot.debugger.DebuggerException;30import sun.jvm.hotspot.debugger.JVMDebugger;31import sun.jvm.hotspot.runtime.VM;3233// generic command line or GUI tool.34// override run & code main as shown below.3536public abstract class Tool implements Runnable {37private HotSpotAgent agent;38private JVMDebugger jvmDebugger;39private int debugeeType;4041// debugeeType is one of constants below42protected static final int DEBUGEE_PID = 0;43protected static final int DEBUGEE_CORE = 1;44protected static final int DEBUGEE_REMOTE = 2;4546public Tool() {47}4849public Tool(JVMDebugger d) {50jvmDebugger = d;51}5253public Tool(HotSpotAgent agent) {54this.agent = agent;55if (agent == null) {56jvmDebugger = null;57debugeeType = -1;58} else {59jvmDebugger = agent.getDebugger();60debugeeType = switch (agent.getStartupMode()) {61case HotSpotAgent.PROCESS_MODE -> DEBUGEE_PID;62case HotSpotAgent.CORE_FILE_MODE -> DEBUGEE_CORE;63case HotSpotAgent.REMOTE_MODE -> DEBUGEE_REMOTE;64default -> throw new IllegalStateException("Invalid attach mode");65};66}67}6869public String getName() {70return getClass().getName();71}7273protected boolean needsJavaPrefix() {74return true;75}7677protected void setAgent(HotSpotAgent a) {78agent = a;79}8081protected void setDebugeeType(int dt) {82debugeeType = dt;83}8485protected HotSpotAgent getAgent() {86return agent;87}8889protected int getDebugeeType() {90return debugeeType;91}9293protected void printUsage() {94String name = null;95if (needsJavaPrefix()) {96name = "java " + getName();97} else {98name = getName();99}100System.out.println("Usage: " + name + " [option] <pid>");101System.out.println("\t\t(to connect to a live java process)");102System.out.println(" or " + name + " [option] <executable> <core>");103System.out.println("\t\t(to connect to a core file)");104System.out.println(" or " + name + " [option] [server_id@]<remote server IP or hostname>");105System.out.println("\t\t(to connect to a remote debug server)");106System.out.println();107System.out.println("where option must be one of:");108printFlagsUsage();109}110111protected void printFlagsUsage() {112System.out.println(" -h | -help\tto print this help message");113}114115protected void usage() {116printUsage();117}118119/*120Derived class main should be of the following form:121122public static void main(String[] args) {123<derived class> obj = new <derived class>;124obj.execute(args);125}126127*/128129protected void execute(String[] args) {130int returnStatus = 1;131132try {133returnStatus = start(args);134} catch (Throwable t) {135t.printStackTrace(System.err);136} finally {137stop();138}139140// Exit with 0 or 1141System.exit(returnStatus);142}143144public void stop() {145if (agent != null) {146agent.detach();147}148}149150private int start(String[] args) {151152if ((args.length < 1) || (args.length > 2)) {153usage();154return 1;155}156157// Attempt to handle -h or -help or some invalid flag158if (args[0].startsWith("-h")) {159usage();160return 0;161} else if (args[0].startsWith("-")) {162usage();163return 1;164}165166PrintStream err = System.err;167PrintStream out = System.out;168169int pid = 0;170String coreFileName = null;171String executableName = null;172String remoteServer = null;173174switch (args.length) {175case 1:176try {177pid = Integer.parseInt(args[0]);178debugeeType = DEBUGEE_PID;179} catch (NumberFormatException e) {180// try remote server181remoteServer = args[0];182debugeeType = DEBUGEE_REMOTE;183}184break;185186case 2:187executableName = args[0];188coreFileName = args[1];189debugeeType = DEBUGEE_CORE;190break;191192default:193usage();194return 1;195}196197agent = new HotSpotAgent();198try {199switch (debugeeType) {200case DEBUGEE_PID:201out.println("Attaching to process ID " + pid + ", please wait...");202agent.attach(pid);203break;204205case DEBUGEE_CORE:206out.println("Attaching to core " + coreFileName +207" from executable " + executableName + ", please wait...");208agent.attach(executableName, coreFileName);209break;210211case DEBUGEE_REMOTE:212out.println("Attaching to remote server " + remoteServer + ", please wait...");213agent.attach(remoteServer);214break;215}216}217catch (DebuggerException e) {218switch (debugeeType) {219case DEBUGEE_PID:220err.print("Error attaching to process: ");221break;222223case DEBUGEE_CORE:224err.print("Error attaching to core file: ");225break;226227case DEBUGEE_REMOTE:228err.print("Error attaching to remote server: ");229break;230}231if (e.getMessage() != null) {232err.println(e.getMessage());233e.printStackTrace();234}235err.println();236return 1;237}238239out.println("Debugger attached successfully.");240startInternal();241return 0;242}243244// When using an existing JVMDebugger.245public void start() {246247if (jvmDebugger == null) {248throw new RuntimeException("Tool.start() called with no JVMDebugger set.");249}250agent = new HotSpotAgent();251agent.attach(jvmDebugger);252startInternal();253}254255// Remains of the start mechanism, common to both start methods.256private void startInternal() {257258PrintStream out = System.out;259VM vm = VM.getVM();260if (vm.isCore()) {261out.println("Core build detected.");262} else if (vm.isClientCompiler()) {263out.println("Client compiler detected.");264} else if (vm.isServerCompiler()) {265out.println("Server compiler detected.");266} else {267throw new RuntimeException("Fatal error: "268+ "should have been able to detect core/C1/C2 build");269}270271String version = vm.getVMRelease();272if (version != null) {273out.print("JVM version is ");274out.println(version);275}276277run();278}279}280281282