Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.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 java.io.BufferedOutputStream;27import java.io.BufferedReader;28import java.io.ByteArrayOutputStream;29import java.io.File;30import java.io.FileInputStream;31import java.io.FileOutputStream;32import java.io.IOException;33import java.io.InputStreamReader;34import java.io.PrintStream;35import java.util.ArrayList;36import java.util.Arrays;37import java.util.Comparator;38import java.util.HashMap;39import java.util.HashSet;40import java.util.Iterator;41import java.util.Stack;42import java.util.regex.Matcher;43import java.util.regex.Pattern;4445import sun.jvm.hotspot.ci.ciEnv;46import sun.jvm.hotspot.code.CodeBlob;47import sun.jvm.hotspot.code.CodeCacheVisitor;48import sun.jvm.hotspot.code.NMethod;49import sun.jvm.hotspot.debugger.Address;50import sun.jvm.hotspot.debugger.OopHandle;51import sun.jvm.hotspot.classfile.ClassLoaderDataGraph;52import sun.jvm.hotspot.memory.FileMapInfo;53import sun.jvm.hotspot.memory.SystemDictionary;54import sun.jvm.hotspot.memory.Universe;55import sun.jvm.hotspot.gc.shared.CollectedHeap;56import sun.jvm.hotspot.gc.g1.G1CollectedHeap;57import sun.jvm.hotspot.oops.DefaultHeapVisitor;58import sun.jvm.hotspot.oops.HeapVisitor;59import sun.jvm.hotspot.oops.InstanceKlass;60import sun.jvm.hotspot.oops.Klass;61import sun.jvm.hotspot.oops.Metadata;62import sun.jvm.hotspot.oops.Method;63import sun.jvm.hotspot.oops.MethodData;64import sun.jvm.hotspot.oops.Oop;65import sun.jvm.hotspot.oops.RawHeapVisitor;66import sun.jvm.hotspot.oops.Symbol;67import sun.jvm.hotspot.oops.UnknownOopException;68import sun.jvm.hotspot.opto.Compile;69import sun.jvm.hotspot.opto.InlineTree;70import sun.jvm.hotspot.runtime.CompiledVFrame;71import sun.jvm.hotspot.runtime.CompilerThread;72import sun.jvm.hotspot.runtime.JavaThread;73import sun.jvm.hotspot.runtime.JavaVFrame;74import sun.jvm.hotspot.runtime.Threads;75import sun.jvm.hotspot.runtime.VM;76import sun.jvm.hotspot.tools.ObjectHistogram;77import sun.jvm.hotspot.tools.JMap;78import sun.jvm.hotspot.tools.PMap;79import sun.jvm.hotspot.tools.PStack;80import sun.jvm.hotspot.tools.StackTrace;81import sun.jvm.hotspot.tools.SysPropsDumper;82import sun.jvm.hotspot.tools.jcore.ClassDump;83import sun.jvm.hotspot.tools.jcore.ClassFilter;84import sun.jvm.hotspot.tools.jcore.ClassWriter;85import sun.jvm.hotspot.types.CIntegerType;86import sun.jvm.hotspot.types.Field;87import sun.jvm.hotspot.types.Type;88import sun.jvm.hotspot.types.basic.BasicType;89import sun.jvm.hotspot.ui.classbrowser.HTMLGenerator;90import sun.jvm.hotspot.ui.tree.CTypeTreeNodeAdapter;91import sun.jvm.hotspot.ui.tree.OopTreeNodeAdapter;92import sun.jvm.hotspot.ui.tree.SimpleTreeNode;93import sun.jvm.hotspot.utilities.AddressOps;94import sun.jvm.hotspot.utilities.Assert;95import sun.jvm.hotspot.utilities.CompactHashTable;96import sun.jvm.hotspot.utilities.HeapProgressThunk;97import sun.jvm.hotspot.utilities.LivenessPathElement;98import sun.jvm.hotspot.utilities.MethodArray;99import sun.jvm.hotspot.utilities.ObjectReader;100import sun.jvm.hotspot.utilities.PointerFinder;101import sun.jvm.hotspot.utilities.PointerLocation;102import sun.jvm.hotspot.utilities.ReversePtrs;103import sun.jvm.hotspot.utilities.ReversePtrsAnalysis;104import sun.jvm.hotspot.utilities.RobustOopDeterminator;105import sun.jvm.hotspot.utilities.SystemDictionaryHelper;106107public class CommandProcessor {108109volatile boolean quit;110111public abstract static class DebuggerInterface {112public abstract HotSpotAgent getAgent();113public abstract boolean isAttached();114public abstract void attach(int pid);115public abstract void attach(String java, String core);116public abstract void attach(String debugServerName);117public abstract void detach();118public abstract void reattach();119}120121public static class BootFilter implements ClassFilter {122public boolean canInclude(InstanceKlass kls) {123return kls.getClassLoader() == null;124}125}126127public static class NonBootFilter implements ClassFilter {128private HashMap<Symbol, InstanceKlass> emitted = new HashMap<>();129public boolean canInclude(InstanceKlass kls) {130if (kls.getClassLoader() == null) return false;131if (emitted.get(kls.getName()) != null) {132// Since multiple class loaders are being shoved133// together duplicate classes are a possibilty. For134// now just ignore them.135return false;136}137emitted.put(kls.getName(), kls);138return true;139}140}141142static class Tokens {143final String input;144int i;145String[] tokens;146int length;147148String[] splitWhitespace(String cmd) {149String[] t = cmd.split("\\s");150if (t.length == 1 && t[0].length() == 0) {151return new String[0];152}153return t;154}155156void add(String s, ArrayList<String> t) {157if (s.length() > 0) {158t.add(s);159}160}161162Tokens(String cmd) {163input = cmd;164// check for quoting165int quote = cmd.indexOf('"');166ArrayList<String> t = new ArrayList<>();167if (quote != -1) {168while (cmd.length() > 0) {169if (quote != -1) {170int endquote = cmd.indexOf('"', quote + 1);171if (endquote == -1) {172throw new RuntimeException("mismatched quotes: " + input);173}174175String before = cmd.substring(0, quote).trim();176String quoted = cmd.substring(quote + 1, endquote);177cmd = cmd.substring(endquote + 1).trim();178if (before.length() > 0) {179String[] w = splitWhitespace(before);180for (int i = 0; i < w.length; i++) {181add(w[i], t);182}183}184add(quoted, t);185quote = cmd.indexOf('"');186} else {187String[] w = splitWhitespace(cmd);188for (int i = 0; i < w.length; i++) {189add(w[i], t);190}191cmd = "";192193}194}195} else {196String[] w = splitWhitespace(cmd);197for (int i = 0; i < w.length; i++) {198add(w[i], t);199}200}201tokens = (String[])t.toArray(new String[0]);202i = 0;203length = tokens.length;204205//for (int i = 0; i < tokens.length; i++) {206// System.out.println("\"" + tokens[i] + "\"");207//}208}209210String nextToken() {211return tokens[i++];212}213boolean hasMoreTokens() {214return i < length;215}216int countTokens() {217return length - i;218}219void trim(int n) {220if (length >= n) {221length -= n;222} else {223throw new IndexOutOfBoundsException(String.valueOf(n));224}225}226String join(String sep) {227StringBuilder result = new StringBuilder();228for (int w = i; w < length; w++) {229result.append(tokens[w]);230if (w + 1 < length) {231result.append(sep);232}233}234return result.toString();235}236237String at(int i) {238if (i < 0 || i >= length) {239throw new IndexOutOfBoundsException(String.valueOf(i));240}241return tokens[i];242}243}244245246abstract class Command {247Command(String n, String u, boolean ok) {248name = n;249usage = u;250okIfDisconnected = ok;251}252253Command(String n, boolean ok) {254name = n;255usage = n;256okIfDisconnected = ok;257}258259final String name;260final String usage;261final boolean okIfDisconnected;262abstract void doit(Tokens t);263void usage() {264out.println("Usage: " + usage);265}266267void printNode(SimpleTreeNode node) {268int count = node.getChildCount();269for (int i = 0; i < count; i++) {270try {271SimpleTreeNode field = node.getChild(i);272out.println(field);273} catch (Exception e) {274out.println();275out.println("Error: " + e);276if (verboseExceptions) {277e.printStackTrace(out);278}279}280}281}282}283284void quote(String s) {285if (s.indexOf(" ") == -1) {286out.print(s);287} else {288out.print("\"");289out.print(s);290out.print("\"");291}292}293294void dumpType(Type type) {295out.print("type ");296quote(type.getName());297out.print(" ");298if (type.getSuperclass() != null) {299quote(type.getSuperclass().getName());300out.print(" ");301} else {302out.print("null ");303}304out.print(type.isOopType());305out.print(" ");306if (type.isCIntegerType()) {307out.print("true ");308out.print(((CIntegerType)type).isUnsigned());309out.print(" ");310} else {311out.print("false false ");312}313out.print(type.getSize());314out.println();315}316317void dumpFields(Type type) {318dumpFields(type, true);319}320321void dumpFields(Type type, boolean allowStatic) {322Iterator i = type.getFields();323while (i.hasNext()) {324Field f = (Field) i.next();325if (!allowStatic && f.isStatic()) continue;326out.print("field ");327quote(type.getName());328out.print(" ");329out.print(f.getName());330out.print(" ");331quote(f.getType().getName());332out.print(" ");333out.print(f.isStatic());334out.print(" ");335if (f.isStatic()) {336out.print("0 ");337out.print(f.getStaticFieldAddress());338} else {339out.print(f.getOffset());340out.print(" 0x0");341}342out.println();343}344}345346347Address lookup(String symbol) {348if (symbol.indexOf("::") != -1) {349String[] parts = symbol.split("::");350StringBuilder mangled = new StringBuilder("__1c");351for (int i = 0; i < parts.length; i++) {352int len = parts[i].length();353if (len >= 26) {354mangled.append((char)('a' + (len / 26)));355len = len % 26;356}357mangled.append((char)('A' + len));358mangled.append(parts[i]);359}360mangled.append("_");361symbol = mangled.toString();362}363return VM.getVM().getDebugger().lookup(null, symbol);364}365366Address parseAddress(String addr) {367return VM.getVM().getDebugger().parseAddress(addr);368}369370private final Command[] commandList = {371new Command("reattach", true) {372public void doit(Tokens t) {373int tokens = t.countTokens();374if (tokens != 0) {375usage();376return;377}378preAttach();379debugger.reattach();380postAttach();381}382},383new Command("attach", "attach pid | exec core | remote_server", true) {384public void doit(Tokens t) {385int tokens = t.countTokens();386if (tokens == 1) {387preAttach();388String arg = t.nextToken();389try {390// Attempt to attach as a PID391debugger.attach(Integer.parseInt(arg));392} catch (NumberFormatException e) {393// Attempt to connect to remote debug server394debugger.attach(arg);395}396postAttach();397} else if (tokens == 2) {398preAttach();399debugger.attach(t.nextToken(), t.nextToken());400postAttach();401} else {402usage();403}404}405},406new Command("detach", false) {407public void doit(Tokens t) {408if (t.countTokens() != 0) {409usage();410} else {411debugger.detach();412}413}414},415new Command("examine", "examine [ address/count ] | [ address,address]", false) {416Pattern args1 = Pattern.compile("^(0x[0-9a-f]+)(/([0-9]*)([a-z]*))?$");417Pattern args2 = Pattern.compile("^(0x[0-9a-f]+),(0x[0-9a-f]+)(/[a-z]*)?$");418419String fill(Address a, int width) {420String s = "0x0";421if (a != null) {422s = a.toString();423}424if (s.length() != width) {425return s.substring(0, 2) + "000000000000000000000".substring(0, width - s.length()) + s.substring(2);426}427return s;428}429430public void doit(Tokens t) {431if (t.countTokens() != 1) {432usage();433} else {434String arg = t.nextToken();435Matcher m1 = args1.matcher(arg);436Matcher m2 = args2.matcher(arg);437Address start = null;438Address end = null;439String format = "";440int formatSize = (int)VM.getVM().getAddressSize();441442if (m1.matches()) {443start = VM.getVM().getDebugger().parseAddress(m1.group(1));444int count = 1;445if (m1.group(2) != null) {446count = Integer.parseInt(m1.group(3));447}448end = start.addOffsetTo(count * formatSize);449} else if (m2.matches()) {450start = VM.getVM().getDebugger().parseAddress(m2.group(1));451end = VM.getVM().getDebugger().parseAddress(m2.group(2));452} else {453usage();454return;455}456int line = 80;457int formatWidth = formatSize * 8 / 4 + 2;458459out.print(fill(start, formatWidth));460out.print(": ");461int width = line - formatWidth - 2;462463boolean needsPrintln = true;464while (start != null && start.lessThan(end)) {465Address val = start.getAddressAt(0);466out.print(fill(val, formatWidth));467needsPrintln = true;468width -= formatWidth;469start = start.addOffsetTo(formatSize);470if (width <= formatWidth) {471out.println();472needsPrintln = false;473if (start.lessThan(end)) {474out.print(fill(start, formatWidth));475out.print(": ");476width = line - formatWidth - 2;477}478} else {479out.print(" ");480width -= 1;481}482}483if (needsPrintln) {484out.println();485}486}487}488},489new Command("dumpreplaydata", "dumpreplaydata { <address > | -a | <thread_id> }", false) {490// This is used to dump replay data from ciInstanceKlass, ciMethodData etc491// default file name is replay.txt, also if java crashes in compiler492// thread, this file will be dumped in error processing.493public void doit(Tokens t) {494if (t.countTokens() != 1) {495usage();496return;497}498String name = t.nextToken();499Address a = null;500try {501a = VM.getVM().getDebugger().parseAddress(name);502} catch (NumberFormatException e) { }503if (a != null) {504// only nmethod, Method, MethodData and InstanceKlass needed to505// dump replay data506507CodeBlob cb = VM.getVM().getCodeCache().findBlob(a);508if (cb != null && (cb instanceof NMethod)) {509((NMethod)cb).dumpReplayData(out);510return;511}512// assume it is Metadata513Metadata meta = Metadata.instantiateWrapperFor(a);514if (meta != null) {515meta.dumpReplayData(out);516} else {517usage();518return;519}520}521// Not an address522boolean all = name.equals("-a");523Threads threads = VM.getVM().getThreads();524for (int i = 0; i < threads.getNumberOfThreads(); i++) {525JavaThread thread = threads.getJavaThreadAt(i);526ByteArrayOutputStream bos = new ByteArrayOutputStream();527thread.printThreadIDOn(new PrintStream(bos));528if (all || bos.toString().equals(name)) {529if (thread instanceof CompilerThread) {530CompilerThread ct = (CompilerThread)thread;531ciEnv env = ct.env();532if (env != null) {533env.dumpReplayData(out);534}535}536}537}538}539},540new Command("buildreplayjars", "buildreplayjars [ all | app | boot ] | [ prefix ]", false) {541// This is used to dump jar files of all the classes542// loaded in the core. Everything with null classloader543// will go in boot.jar and everything else will go in544// app.jar. boot.jar usually not needed, unless changed by jvmti.545public void doit(Tokens t) {546int tcount = t.countTokens();547if (tcount > 2) {548usage();549return;550}551try {552String prefix = "";553String option = "all"; // default554switch(tcount) {555case 0:556break;557case 1:558option = t.nextToken();559if (!option.equalsIgnoreCase("all") && !option.equalsIgnoreCase("app") &&560!option.equalsIgnoreCase("root")) {561prefix = option;562option = "all";563}564break;565case 2:566option = t.nextToken();567prefix = t.nextToken();568break;569default:570usage();571return;572}573if (!option.equalsIgnoreCase("all") && !option.equalsIgnoreCase("app") &&574!option.equalsIgnoreCase("boot")) {575usage();576return;577}578ClassDump cd = new ClassDump();579if (option.equalsIgnoreCase("all") || option.equalsIgnoreCase("boot")) {580cd.setClassFilter(new BootFilter());581cd.setJarOutput(prefix + "boot.jar");582cd.run();583}584if (option.equalsIgnoreCase("all") || option.equalsIgnoreCase("app")) {585cd.setClassFilter(new NonBootFilter());586cd.setJarOutput(prefix + "app.jar");587cd.run();588}589} catch (IOException ioe) {590ioe.printStackTrace();591}592}593},594new Command("findsym", "findsym name", false) {595public void doit(Tokens t) {596if (t.countTokens() != 1) {597usage();598} else {599String result = VM.getVM().getDebugger().findSymbol(t.nextToken());600out.println(result == null ? "Symbol not found" : result);601}602}603},604new Command("findpc", "findpc address", false) {605public void doit(Tokens t) {606if (t.countTokens() != 1) {607usage();608} else {609Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());610PointerLocation loc = PointerFinder.find(a);611loc.printOn(out);612}613}614},615new Command("symbol", "symbol address", false) {616public void doit(Tokens t) {617if (t.countTokens() != 1) {618usage();619} else {620Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());621Symbol.create(a).printValueOn(out);622out.println();623}624}625},626new Command("flags", "flags [ flag | -nd ]", false) {627public void doit(Tokens t) {628int tokens = t.countTokens();629if (tokens != 0 && tokens != 1) {630usage();631} else {632String name = tokens > 0 ? t.nextToken() : null;633boolean nonDefault = false;634if (name != null && name.equals("-nd")) {635name = null;636nonDefault = true;637}638639VM.Flag[] flags = VM.getVM().getCommandLineFlags();640if (flags == null) {641out.println("Command Flag info not available (use 1.4.1_03 or later)!");642} else {643boolean printed = false;644for (int f = 0; f < flags.length; f++) {645VM.Flag flag = flags[f];646if (name == null || flag.getName().equals(name)) {647648if (nonDefault && (flag.getOrigin() == VM.Flags_DEFAULT)) {649// only print flags which aren't their defaults650continue;651}652out.println(flag.getName() + " = " + flag.getValue() + " " + flag.getOriginString());653printed = true;654}655}656if (name != null && !printed) {657out.println("Couldn't find flag: " + name);658}659}660}661}662},663new Command("help", "help [ command ]", true) {664public void doit(Tokens t) {665int tokens = t.countTokens();666Command cmd = null;667if (tokens == 1) {668cmd = findCommand(t.nextToken());669}670671if (cmd != null) {672cmd.usage();673} else if (tokens == 0) {674out.println("Available commands:");675Object[] keys = commands.keySet().toArray();676Arrays.sort(keys, new Comparator<>() {677public int compare(Object o1, Object o2) {678return o1.toString().compareTo(o2.toString());679}680});681for (int i = 0; i < keys.length; i++) {682out.print(" ");683out.println(((Command)commands.get(keys[i])).usage);684}685}686}687},688new Command("history", "history", true) {689public void doit(Tokens t) {690int tokens = t.countTokens();691if (tokens != 0 && (tokens != 1 || !t.nextToken().equals("-h"))) {692usage();693return;694}695boolean printIndex = tokens == 0;696for (int i = 0; i < history.size(); i++) {697if (printIndex) out.print(i + " ");698out.println(history.get(i));699}700}701},702// decode raw address703new Command("dis", "dis address [length]", false) {704public void doit(Tokens t) {705int tokens = t.countTokens();706if (tokens != 1 && tokens != 2) {707usage();708return;709}710String name = t.nextToken();711Address addr = null;712int len = 0x10; // default length713try {714addr = VM.getVM().getDebugger().parseAddress(name);715} catch (NumberFormatException e) {716out.println(e);717return;718}719if (tokens == 2) {720try {721len = Integer.parseInt(t.nextToken());722} catch (NumberFormatException e) {723out.println(e);724return;725}726}727HTMLGenerator generator = new HTMLGenerator(false);728out.println(generator.genHTMLForRawDisassembly(addr, len));729}730731},732// decode codeblob or nmethod733new Command("disassemble", "disassemble address", false) {734public void doit(Tokens t) {735int tokens = t.countTokens();736if (tokens != 1) {737usage();738return;739}740String name = t.nextToken();741Address addr = null;742try {743addr = VM.getVM().getDebugger().parseAddress(name);744} catch (NumberFormatException e) {745out.println(e);746return;747}748749HTMLGenerator generator = new HTMLGenerator(false);750out.println(generator.genHTML(addr));751}752},753// print Java bytecode disassembly754new Command("jdis", "jdis address", false) {755public void doit(Tokens t) {756int tokens = t.countTokens();757if (tokens != 1) {758usage();759return;760}761Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());762Method m = (Method)Metadata.instantiateWrapperFor(a);763HTMLGenerator html = new HTMLGenerator(false);764out.println(html.genHTML(m));765}766},767new Command("revptrs", "revptrs address", false) {768public void doit(Tokens t) {769int tokens = t.countTokens();770if (tokens != 1 && (tokens != 2 || !t.nextToken().equals("-c"))) {771usage();772return;773}774boolean chase = tokens == 2;775ReversePtrs revptrs = VM.getVM().getRevPtrs();776if (revptrs == null) {777out.println("Computing reverse pointers...");778ReversePtrsAnalysis analysis = new ReversePtrsAnalysis();779final boolean[] complete = new boolean[1];780HeapProgressThunk thunk = new HeapProgressThunk() {781public void heapIterationFractionUpdate(double d) {}782public synchronized void heapIterationComplete() {783complete[0] = true;784notify();785}786};787analysis.setHeapProgressThunk(thunk);788analysis.run();789while (!complete[0]) {790synchronized (thunk) {791try {792thunk.wait();793} catch (Exception e) {794}795}796}797revptrs = VM.getVM().getRevPtrs();798out.println("Done.");799}800Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());801if (VM.getVM().getUniverse().heap().isInReserved(a)) {802OopHandle handle = a.addOffsetToAsOopHandle(0);803Oop oop = VM.getVM().getObjectHeap().newOop(handle);804ArrayList ptrs = revptrs.get(oop);805if (ptrs == null) {806out.println("no live references to " + a);807} else {808if (chase) {809while (ptrs.size() == 1) {810LivenessPathElement e = (LivenessPathElement)ptrs.get(0);811ByteArrayOutputStream bos = new ByteArrayOutputStream();812Oop.printOopValueOn(e.getObj(), new PrintStream(bos));813out.println(bos.toString());814ptrs = revptrs.get(e.getObj());815}816} else {817for (int i = 0; i < ptrs.size(); i++) {818LivenessPathElement e = (LivenessPathElement)ptrs.get(i);819ByteArrayOutputStream bos = new ByteArrayOutputStream();820Oop.printOopValueOn(e.getObj(), new PrintStream(bos));821out.println(bos.toString());822oop = e.getObj();823}824}825}826}827}828},829new Command("printmdo", "printmdo [ -a | expression ]", false) {830// Print every MDO in the heap or the one referenced by expression.831public void doit(Tokens t) {832if (t.countTokens() != 1) {833usage();834} else {835String s = t.nextToken();836if (s.equals("-a")) {837ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();838cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {839public void visit(Klass k) {840if (k instanceof InstanceKlass) {841MethodArray methods = ((InstanceKlass)k).getMethods();842for (int i = 0; i < methods.length(); i++) {843Method m = methods.at(i);844MethodData mdo = m.getMethodData();845if (mdo != null) {846out.println("MethodData " + mdo.getAddress() + " for " +847"method " + m.getMethodHolder().getName().asString() + "." +848m.getName().asString() +849m.getSignature().asString() + "@" + m.getAddress());850mdo.printDataOn(out);851}852}853}854}855}856);857} else {858Address a = VM.getVM().getDebugger().parseAddress(s);859MethodData mdo = (MethodData) Metadata.instantiateWrapperFor(a);860mdo.printDataOn(out);861}862}863}864},865new Command("printall", "printall", false) {866// Print every MDO in the heap or the one referenced by expression.867public void doit(Tokens t) {868if (t.countTokens() != 0) {869usage();870} else {871ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();872cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {873public void visit(Klass k) {874if (k instanceof InstanceKlass && ((InstanceKlass)k).getConstants().getCache() != null) {875MethodArray methods = ((InstanceKlass)k).getMethods();876for (int i = 0; i < methods.length(); i++) {877Method m = methods.at(i);878HTMLGenerator gen = new HTMLGenerator(false);879out.println(gen.genHTML(m));880}881}882}883}884);885}886}887},888new Command("dumpideal", "dumpideal { -a | id }", false) {889// Do a full dump of the nodes reachable from root in each compiler thread.890public void doit(Tokens t) {891if (t.countTokens() != 1) {892usage();893} else {894String name = t.nextToken();895boolean all = name.equals("-a");896Threads threads = VM.getVM().getThreads();897for (int i = 0; i < threads.getNumberOfThreads(); i++) {898JavaThread thread = threads.getJavaThreadAt(i);899ByteArrayOutputStream bos = new ByteArrayOutputStream();900thread.printThreadIDOn(new PrintStream(bos));901if (all || bos.toString().equals(name)) {902if (thread instanceof CompilerThread) {903CompilerThread ct = (CompilerThread)thread;904out.println(ct);905ciEnv env = ct.env();906if (env != null) {907Compile c = env.compilerData();908c.root().dump(9999, out);909} else {910out.println(" not compiling");911}912}913}914}915}916}917},918new Command("dumpcfg", "dumpcfg { -a | id }", false) {919// Dump the PhaseCFG for every compiler thread that has one live.920public void doit(Tokens t) {921if (t.countTokens() != 1) {922usage();923} else {924String name = t.nextToken();925boolean all = name.equals("-a");926Threads threads = VM.getVM().getThreads();927for (int i = 0; i < threads.getNumberOfThreads(); i++) {928JavaThread thread = threads.getJavaThreadAt(i);929ByteArrayOutputStream bos = new ByteArrayOutputStream();930thread.printThreadIDOn(new PrintStream(bos));931if (all || bos.toString().equals(name)) {932if (thread instanceof CompilerThread) {933CompilerThread ct = (CompilerThread)thread;934out.println(ct);935ciEnv env = ct.env();936if (env != null) {937Compile c = env.compilerData();938c.cfg().dump(out);939}940}941}942}943}944}945},946new Command("dumpilt", "dumpilt { -a | id }", false) {947// dumps the InlineTree of a C2 compile948public void doit(Tokens t) {949if (t.countTokens() != 1) {950usage();951} else {952String name = t.nextToken();953boolean all = name.equals("-a");954Threads threads = VM.getVM().getThreads();955for (int i = 0; i < threads.getNumberOfThreads(); i++) {956JavaThread thread = threads.getJavaThreadAt(i);957ByteArrayOutputStream bos = new ByteArrayOutputStream();958thread.printThreadIDOn(new PrintStream(bos));959if (all || bos.toString().equals(name)) {960if (thread instanceof CompilerThread) {961CompilerThread ct = (CompilerThread)thread;962ciEnv env = ct.env();963if (env != null) {964Compile c = env.compilerData();965InlineTree ilt = c.ilt();966if (ilt != null) {967ilt.print(out);968}969}970}971}972}973}974}975},976new Command("vmstructsdump", "vmstructsdump", false) {977public void doit(Tokens t) {978if (t.countTokens() != 0) {979usage();980return;981}982983// Dump a copy of the type database in a form that can984// be read back.985Iterator i = agent.getTypeDataBase().getTypes();986// Make sure the types are emitted in an order than can be read back in987HashSet<String> emitted = new HashSet<>();988Stack<Type> pending = new Stack<>();989while (i.hasNext()) {990Type n = (Type)i.next();991if (emitted.contains(n.getName())) {992continue;993}994995while (n != null && !emitted.contains(n.getName())) {996pending.push(n);997n = n.getSuperclass();998}999while (!pending.empty()) {1000n = (Type)pending.pop();1001dumpType(n);1002emitted.add(n.getName());1003}1004}1005i = agent.getTypeDataBase().getTypes();1006while (i.hasNext()) {1007dumpFields((Type)i.next(), false);1008}1009}1010},10111012new Command("inspect", "inspect expression", false) {1013public void doit(Tokens t) {1014if (t.countTokens() != 1) {1015usage();1016} else {1017Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());1018SimpleTreeNode node = null;1019if (VM.getVM().getUniverse().heap().isInReserved(a)) {1020OopHandle handle = a.addOffsetToAsOopHandle(0);1021Oop oop = VM.getVM().getObjectHeap().newOop(handle);1022node = new OopTreeNodeAdapter(oop, null);10231024out.println("instance of " + node.getValue() +1025" (size = " + oop.getObjectSize() + ")");1026} else if (VM.getVM().getCodeCache().contains(a)) {1027CodeBlob blob = VM.getVM().getCodeCache().findBlobUnsafe(a);1028a = blob.headerBegin();1029}1030if (node == null) {1031Type type = VM.getVM().getTypeDataBase().guessTypeForAddress(a);1032if (type == null && VM.getVM().isSharingEnabled()) {1033// Check if the value falls in the _md_region1034Address loc1 = a.getAddressAt(0);1035FileMapInfo cdsFileMapInfo = VM.getVM().getFileMapInfo();1036if (cdsFileMapInfo.inCopiedVtableSpace(loc1)) {1037type = cdsFileMapInfo.getTypeForVptrAddress(loc1);1038}10391040}1041if (type != null) {1042out.println("Type is " + type.getName() + " (size of " + type.getSize() + ")");1043node = new CTypeTreeNodeAdapter(a, type, null);1044}1045}1046if (node != null) {1047printNode(node);1048}1049}1050}1051},1052new Command("jhisto", "jhisto", false) {1053public void doit(Tokens t) {1054ObjectHistogram histo = new ObjectHistogram();1055histo.run(out, err);1056}1057},1058new Command("jstack", "jstack [-v]", false) {1059public void doit(Tokens t) {1060boolean verbose = false;1061if (t.countTokens() > 0 && t.nextToken().equals("-v")) {1062verbose = true;1063}1064StackTrace jstack = new StackTrace(verbose, true);1065jstack.run(out);1066}1067},1068new Command("print", "print expression", false) {1069public void doit(Tokens t) {1070if (t.countTokens() != 1) {1071usage();1072} else {1073Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());1074HTMLGenerator gen = new HTMLGenerator(false);1075out.println(gen.genHTML(a));1076}1077}1078},1079new Command("printas", "printas type expression", false) {1080public void doit(Tokens t) {1081if (t.countTokens() != 2) {1082usage();1083} else {1084Type type = agent.getTypeDataBase().lookupType(t.nextToken());1085Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());1086CTypeTreeNodeAdapter node = new CTypeTreeNodeAdapter(a, type, null);10871088out.println("pointer to " + type + " @ " + a +1089" (size = " + type.getSize() + ")");1090printNode(node);1091}1092}1093},1094new Command("printstatics", "printstatics [ type ]", false) {1095public void doit(Tokens t) {1096if (t.countTokens() > 1) {1097usage();1098} else {1099if (t.countTokens() == 0) {1100out.println("All known static fields");1101printNode(new CTypeTreeNodeAdapter(agent.getTypeDataBase().getTypes()));1102} else {1103Type type = agent.getTypeDataBase().lookupType(t.nextToken());1104out.println("Static fields of " + type.getName());1105printNode(new CTypeTreeNodeAdapter(type));1106}1107}1108}1109},1110new Command("pmap", "pmap", false) {1111public void doit(Tokens t) {1112PMap pmap = new PMap(debugger.getAgent());1113pmap.run(out, debugger.getAgent().getDebugger());1114}1115},1116new Command("pstack", "pstack [-v]", false) {1117public void doit(Tokens t) {1118boolean verbose = false;1119if (t.countTokens() > 0 && t.nextToken().equals("-v")) {1120verbose = true;1121}1122PStack pstack = new PStack(verbose, true, debugger.getAgent());1123pstack.run(out, debugger.getAgent().getDebugger());1124}1125},1126new Command("quit", true) {1127public void doit(Tokens t) {1128if (t.countTokens() != 0) {1129usage();1130} else {1131debugger.detach();1132quit = true;1133}1134}1135},1136new Command("echo", "echo [ true | false ]", true) {1137public void doit(Tokens t) {1138if (t.countTokens() == 0) {1139out.println("echo is " + doEcho);1140} else if (t.countTokens() == 1) {1141doEcho = Boolean.valueOf(t.nextToken()).booleanValue();1142} else {1143usage();1144}1145}1146},1147new Command("versioncheck", "versioncheck [ true | false ]", true) {1148public void doit(Tokens t) {1149if (t.countTokens() == 0) {1150out.println("versioncheck is " +1151(System.getProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck") == null));1152} else if (t.countTokens() == 1) {1153if (Boolean.valueOf(t.nextToken()).booleanValue()) {1154System.clearProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck");1155} else {1156System.setProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck", "true");1157}1158} else {1159usage();1160}1161}1162},1163new Command("scanoops", "scanoops start end [ type ]", false) {1164public void doit(Tokens t) {1165if (t.countTokens() != 2 && t.countTokens() != 3) {1166usage();1167} else {1168long stride = VM.getVM().getAddressSize();1169Address base = VM.getVM().getDebugger().parseAddress(t.nextToken());1170Address end = VM.getVM().getDebugger().parseAddress(t.nextToken());1171Klass klass = null;1172if (t.countTokens() == 1) {1173klass = SystemDictionaryHelper.findInstanceKlass(t.nextToken());1174if (klass == null) {1175out.println("No such type.");1176return;1177}1178}1179while (base != null && base.lessThan(end)) {1180long step = stride;1181OopHandle handle = base.addOffsetToAsOopHandle(0);1182if (RobustOopDeterminator.oopLooksValid(handle)) {1183try {1184Oop oop = VM.getVM().getObjectHeap().newOop(handle);1185if (klass == null || oop.getKlass().isSubtypeOf(klass))1186out.println(handle.toString() + " " + oop.getKlass().getName().asString());1187step = oop.getObjectSize();1188} catch (UnknownOopException ex) {1189// ok1190} catch (RuntimeException ex) {1191ex.printStackTrace();1192}1193}1194base = base.addOffsetTo(step);1195}1196}1197}1198},1199new Command("intConstant", "intConstant [ name [ value ] ]", false) {1200public void doit(Tokens t) {1201if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 2) {1202usage();1203return;1204}1205HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();1206if (t.countTokens() == 1) {1207String name = t.nextToken();1208out.println("intConstant " + name + " " + db.lookupIntConstant(name));1209} else if (t.countTokens() == 0) {1210Iterator i = db.getIntConstants();1211while (i.hasNext()) {1212String name = (String)i.next();1213out.println("intConstant " + name + " " + db.lookupIntConstant(name));1214}1215} else if (t.countTokens() == 2) {1216String name = t.nextToken();1217Integer value = Integer.valueOf(t.nextToken());1218db.addIntConstant(name, value);1219}1220}1221},1222new Command("longConstant", "longConstant [ name [ value ] ]", false) {1223public void doit(Tokens t) {1224if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 2) {1225usage();1226return;1227}1228HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();1229if (t.countTokens() == 1) {1230String name = t.nextToken();1231out.println("longConstant " + name + " " + db.lookupLongConstant(name));1232} else if (t.countTokens() == 0) {1233Iterator i = db.getLongConstants();1234while (i.hasNext()) {1235String name = (String)i.next();1236out.println("longConstant " + name + " " + db.lookupLongConstant(name));1237}1238} else if (t.countTokens() == 2) {1239String name = t.nextToken();1240Long value = Long.valueOf(t.nextToken());1241db.addLongConstant(name, value);1242}1243}1244},1245new Command("field", "field [ type [ name fieldtype isStatic offset address ] ]", false) {1246public void doit(Tokens t) {1247if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) {1248usage();1249return;1250}1251if (t.countTokens() == 1) {1252Type type = agent.getTypeDataBase().lookupType(t.nextToken());1253dumpFields(type);1254} else if (t.countTokens() == 0) {1255Iterator i = agent.getTypeDataBase().getTypes();1256while (i.hasNext()) {1257dumpFields((Type)i.next());1258}1259} else {1260BasicType containingType = (BasicType)agent.getTypeDataBase().lookupType(t.nextToken());12611262String fieldName = t.nextToken();12631264// The field's Type must already be in the database -- no exceptions1265Type fieldType = agent.getTypeDataBase().lookupType(t.nextToken());12661267boolean isStatic = Boolean.valueOf(t.nextToken()).booleanValue();1268long offset = Long.parseLong(t.nextToken());1269Address staticAddress = parseAddress(t.nextToken());1270if (isStatic && staticAddress == null) {1271staticAddress = lookup(containingType.getName() + "::" + fieldName);1272}12731274// check to see if the field already exists1275Iterator i = containingType.getFields();1276while (i.hasNext()) {1277Field f = (Field) i.next();1278if (f.getName().equals(fieldName)) {1279if (f.isStatic() != isStatic) {1280throw new RuntimeException("static/nonstatic mismatch: " + t.input);1281}1282if (!isStatic) {1283if (f.getOffset() != offset) {1284throw new RuntimeException("bad redefinition of field offset: " + t.input);1285}1286} else {1287if (!f.getStaticFieldAddress().equals(staticAddress)) {1288throw new RuntimeException("bad redefinition of field location: " + t.input);1289}1290}1291if (f.getType() != fieldType) {1292throw new RuntimeException("bad redefinition of field type: " + t.input);1293}1294return;1295}1296}12971298// Create field by type1299HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();1300db.createField(containingType,1301fieldName, fieldType,1302isStatic,1303offset,1304staticAddress);13051306}1307}13081309},1310new Command("tokenize", "tokenize ...", true) {1311public void doit(Tokens t) {1312while (t.hasMoreTokens()) {1313out.println("\"" + t.nextToken() + "\"");1314}1315}1316},1317new Command("type", "type [ type [ name super isOop isInteger isUnsigned size ] ]", false) {1318public void doit(Tokens t) {1319if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) {1320usage();1321return;1322}1323if (t.countTokens() == 6) {1324String typeName = t.nextToken();1325String superclassName = t.nextToken();1326if (superclassName.equals("null")) {1327superclassName = null;1328}1329boolean isOop = Boolean.valueOf(t.nextToken()).booleanValue();1330boolean isInteger = Boolean.valueOf(t.nextToken()).booleanValue();1331boolean isUnsigned = Boolean.valueOf(t.nextToken()).booleanValue();1332long size = Long.parseLong(t.nextToken());13331334BasicType type = null;1335try {1336type = (BasicType)agent.getTypeDataBase().lookupType(typeName);1337} catch (RuntimeException e) {1338}1339if (type != null) {1340if (type.isOopType() != isOop) {1341throw new RuntimeException("oop mismatch in type definition: " + t.input);1342}1343if (type.isCIntegerType() != isInteger) {1344throw new RuntimeException("integer type mismatch in type definition: " + t.input);1345}1346if (type.isCIntegerType() && (((CIntegerType)type).isUnsigned()) != isUnsigned) {1347throw new RuntimeException("unsigned mismatch in type definition: " + t.input);1348}1349if (type.getSuperclass() == null) {1350if (superclassName != null) {1351if (type.getSize() == -1) {1352type.setSuperclass(agent.getTypeDataBase().lookupType(superclassName));1353} else {1354throw new RuntimeException("unexpected superclass in type definition: " + t.input);1355}1356}1357} else {1358if (superclassName == null) {1359throw new RuntimeException("missing superclass in type definition: " + t.input);1360}1361if (!type.getSuperclass().getName().equals(superclassName)) {1362throw new RuntimeException("incorrect superclass in type definition: " + t.input);1363}1364}1365if (type.getSize() != size) {1366if (type.getSize() == -1) {1367type.setSize(size);1368}1369throw new RuntimeException("size mismatch in type definition: " + t.input);1370}1371return;1372}13731374// Create type1375HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();1376db.createType(typeName, superclassName, isOop, isInteger, isUnsigned, size);1377} else if (t.countTokens() == 1) {1378Type type = agent.getTypeDataBase().lookupType(t.nextToken());1379dumpType(type);1380} else {1381Iterator i = agent.getTypeDataBase().getTypes();1382// Make sure the types are emitted in an order than can be read back in1383HashSet<String> emitted = new HashSet<>();1384Stack<Type> pending = new Stack<>();1385while (i.hasNext()) {1386Type n = (Type)i.next();1387if (emitted.contains(n.getName())) {1388continue;1389}13901391while (n != null && !emitted.contains(n.getName())) {1392pending.push(n);1393n = n.getSuperclass();1394}1395while (!pending.empty()) {1396n = (Type)pending.pop();1397dumpType(n);1398emitted.add(n.getName());1399}1400}1401}1402}14031404},1405new Command("source", "source filename", true) {1406public void doit(Tokens t) {1407if (t.countTokens() != 1) {1408usage();1409return;1410}1411String file = t.nextToken();1412BufferedReader savedInput = in;1413try {1414BufferedReader input = new BufferedReader(new InputStreamReader(new FileInputStream(file)));1415in = input;1416run(false);1417} catch (Exception e) {1418out.println("Error: " + e);1419if (verboseExceptions) {1420e.printStackTrace(out);1421}1422} finally {1423in = savedInput;1424}14251426}1427},1428new Command("search", "search [ heap | perm | rawheap | codecache | threads ] value", false) {1429public void doit(Tokens t) {1430if (t.countTokens() != 2) {1431usage();1432return;1433}1434String type = t.nextToken();1435final Address value = VM.getVM().getDebugger().parseAddress(t.nextToken());1436final long stride = VM.getVM().getAddressSize();1437if (type.equals("threads")) {1438Threads threads = VM.getVM().getThreads();1439for (int i = 0; i < threads.getNumberOfThreads(); i++) {1440JavaThread thread = threads.getJavaThreadAt(i);1441Address base = thread.getStackBase();1442Address end = thread.getLastJavaSP();1443if (end == null) continue;1444if (end.lessThan(base)) {1445Address tmp = base;1446base = end;1447end = tmp;1448}1449//out.println("Searching " + base + " " + end);1450while (base != null && base.lessThan(end)) {1451Address val = base.getAddressAt(0);1452if (AddressOps.equal(val, value)) {1453ByteArrayOutputStream bos = new ByteArrayOutputStream();1454thread.printThreadIDOn(new PrintStream(bos));1455out.println("found on the stack of thread " + bos.toString() + " at " + base);1456}1457base = base.addOffsetTo(stride);1458}1459}1460} else if (type.equals("rawheap")) {1461RawHeapVisitor iterator = new RawHeapVisitor() {1462public void prologue(long used) {1463}14641465public void visitAddress(Address addr) {1466Address val = addr.getAddressAt(0);1467if (AddressOps.equal(val, value)) {1468out.println("found at " + addr);1469}1470}1471public void visitCompOopAddress(Address addr) {1472Address val = addr.getCompOopAddressAt(0);1473if (AddressOps.equal(val, value)) {1474out.println("found at " + addr);1475}1476}1477public void epilogue() {1478}1479};1480VM.getVM().getObjectHeap().iterateRaw(iterator);1481} else if (type.equals("heap")) {1482HeapVisitor iterator = new DefaultHeapVisitor() {1483public boolean doObj(Oop obj) {1484int index = 0;1485Address start = obj.getHandle();1486long end = obj.getObjectSize();1487while (index < end) {1488Address val = start.getAddressAt(index);1489if (AddressOps.equal(val, value)) {1490out.println("found in " + obj.getHandle());1491break;1492}1493index += 4;1494}1495return false;1496}1497};1498VM.getVM().getObjectHeap().iterate(iterator);1499} else if (type.equals("codecache")) {1500CodeCacheVisitor v = new CodeCacheVisitor() {1501public void prologue(Address start, Address end) {1502}1503public void visit(CodeBlob blob) {1504boolean printed = false;1505Address base = blob.getAddress();1506Address end = base.addOffsetTo(blob.getSize());1507while (base != null && base.lessThan(end)) {1508Address val = base.getAddressAt(0);1509if (AddressOps.equal(val, value)) {1510if (!printed) {1511printed = true;1512try {1513blob.printOn(out);1514} catch (Exception e) {1515out.println("Exception printing blob at " + base);1516e.printStackTrace();1517}1518}1519out.println("found at " + base + "\n");1520}1521base = base.addOffsetTo(stride);1522}1523}1524public void epilogue() {1525}152615271528};1529VM.getVM().getCodeCache().iterate(v);15301531}1532}1533},1534new Command("dumpcodecache", "dumpcodecache", false) {1535public void doit(Tokens t) {1536if (t.countTokens() != 0) {1537usage();1538} else {1539final PrintStream fout = out;1540final HTMLGenerator gen = new HTMLGenerator(false);1541CodeCacheVisitor v = new CodeCacheVisitor() {1542public void prologue(Address start, Address end) {1543}1544public void visit(CodeBlob blob) {1545fout.println(gen.genHTML(blob.contentBegin()));1546}1547public void epilogue() {1548}154915501551};1552VM.getVM().getCodeCache().iterate(v);1553}1554}1555},1556new Command("where", "where { -a | id }", false) {1557public void doit(Tokens t) {1558if (t.countTokens() != 1) {1559usage();1560} else {1561String name = t.nextToken();1562Threads threads = VM.getVM().getThreads();1563boolean all = name.equals("-a");1564for (int i = 0; i < threads.getNumberOfThreads(); i++) {1565JavaThread thread = threads.getJavaThreadAt(i);1566ByteArrayOutputStream bos = new ByteArrayOutputStream();1567thread.printThreadIDOn(new PrintStream(bos));1568if (all || bos.toString().equals(name)) {1569out.println("Thread " + bos.toString() + " Address: " + thread.getAddress());1570HTMLGenerator gen = new HTMLGenerator(false);1571try {1572out.println(gen.genHTMLForJavaStackTrace(thread));1573} catch (Exception e) {1574err.println("Error: " + e);1575if (verboseExceptions) {1576e.printStackTrace(err);1577}1578}1579if (!all) return;1580}1581}1582if (!all) out.println("Couldn't find thread " + name);1583}1584}1585},1586new Command("thread", "thread { -a | id }", false) {1587public void doit(Tokens t) {1588if (t.countTokens() != 1) {1589usage();1590} else {1591String name = t.nextToken();1592Threads threads = VM.getVM().getThreads();1593boolean all = name.equals("-a");1594for (int i = 0; i < threads.getNumberOfThreads(); i++) {1595JavaThread thread = threads.getJavaThreadAt(i);1596ByteArrayOutputStream bos = new ByteArrayOutputStream();1597thread.printThreadIDOn(new PrintStream(bos));1598if (all || bos.toString().equals(name)) {1599out.println("Thread " + bos.toString() + " Address " + thread.getAddress());1600thread.printInfoOn(out);1601out.println(" ");1602if (!all) return;1603}1604}1605if (!all) {1606out.println("Couldn't find thread " + name);1607}1608}1609}1610},16111612new Command("threads", false) {1613public void doit(Tokens t) {1614if (t.countTokens() != 0) {1615usage();1616} else {1617Threads threads = VM.getVM().getThreads();1618for (int i = 0; i < threads.getNumberOfThreads(); i++) {1619JavaThread thread = threads.getJavaThreadAt(i);1620thread.printThreadIDOn(out);1621out.println(" " + thread.getThreadName());1622thread.printInfoOn(out);1623out.println("\n...");1624}1625}1626}1627},16281629new Command("livenmethods", false) {1630public void doit(Tokens t) {1631if (t.countTokens() != 0) {1632usage();1633} else {1634ArrayList<NMethod> nmethods = new ArrayList<>();1635Threads threads = VM.getVM().getThreads();1636HTMLGenerator gen = new HTMLGenerator(false);1637for (int i = 0; i < threads.getNumberOfThreads(); i++) {1638JavaThread thread = threads.getJavaThreadAt(i);1639try {1640for (JavaVFrame vf = thread.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {1641if (vf instanceof CompiledVFrame) {1642NMethod c = ((CompiledVFrame)vf).getCode();1643if (!nmethods.contains(c)) {1644nmethods.add(c);1645out.println(gen.genHTML(c));1646}1647}1648}1649} catch (Exception e) {1650e.printStackTrace();1651}1652}1653}1654}1655},1656new Command("g1regiondetails", false) {1657public void doit(Tokens t) {1658if (t.countTokens() != 0) {1659usage();1660} else {1661CollectedHeap heap = VM.getVM().getUniverse().heap();1662if (!(heap instanceof G1CollectedHeap)) {1663out.println("This command is valid only for G1GC.");1664return;1665}1666out.println("Region Details:");1667((G1CollectedHeap)heap).printRegionDetails(out);1668}1669}1670},1671new Command("universe", false) {1672public void doit(Tokens t) {1673if (t.countTokens() != 0) {1674usage();1675} else {1676Universe u = VM.getVM().getUniverse();1677out.println("Heap Parameters:");1678u.heap().printOn(out);1679}1680}1681},1682new Command("verbose", "verbose true | false", true) {1683public void doit(Tokens t) {1684if (t.countTokens() != 1) {1685usage();1686} else {1687verboseExceptions = Boolean.valueOf(t.nextToken()).booleanValue();1688}1689}1690},1691new Command("assert", "assert true | false", true) {1692public void doit(Tokens t) {1693if (t.countTokens() != 1) {1694usage();1695} else {1696Assert.ASSERTS_ENABLED = Boolean.valueOf(t.nextToken()).booleanValue();1697}1698}1699},1700new Command("dumpclass", "dumpclass {address | name} [directory]", false) {1701public void doit(Tokens t) {1702int tokenCount = t.countTokens();1703if (tokenCount != 1 && tokenCount != 2) {1704usage();1705return;1706}17071708/* Find the InstanceKlass for specified class name or class address. */1709InstanceKlass ik = null;1710String classname = t.nextToken();1711if (classname.startsWith("0x")) {1712// treat it as address1713VM vm = VM.getVM();1714Address addr = vm.getDebugger().parseAddress(classname);1715Metadata metadata = Metadata.instantiateWrapperFor(addr.addOffsetTo(0));1716if (metadata instanceof InstanceKlass) {1717ik = (InstanceKlass) metadata;1718} else {1719out.println("Specified address is not an InstanceKlass");1720return;1721}1722} else {1723ik = SystemDictionaryHelper.findInstanceKlass(classname);1724if (ik == null) {1725out.println("class not found: " + classname);1726return;1727}1728}17291730/* Compute filename for class. */1731StringBuilder buf = new StringBuilder();1732if (tokenCount > 1) {1733buf.append(t.nextToken());1734} else {1735buf.append('.');1736}1737buf.append(File.separatorChar);1738buf.append(ik.getName().asString().replace('/', File.separatorChar));1739buf.append(".class");1740String fileName = buf.toString();1741File file = new File(fileName);17421743/* Dump the class file. */1744try {1745int index = fileName.lastIndexOf(File.separatorChar);1746File dir = new File(fileName.substring(0, index));1747dir.mkdirs();1748try (FileOutputStream fos = new FileOutputStream(file)) {1749ClassWriter cw = new ClassWriter(ik, fos);1750cw.write();1751}1752} catch (Exception e) {1753err.println("Error: " + e);1754if (verboseExceptions) {1755e.printStackTrace(err);1756}1757}1758}1759},1760new Command("sysprops", "sysprops", false) {1761public void doit(Tokens t) {1762if (t.countTokens() != 0) {1763usage();1764return;1765}1766SysPropsDumper sysProps = new SysPropsDumper();1767sysProps.run();1768}1769},1770new Command("dumpheap", "dumpheap [gz=<1-9>] [filename]", false) {1771public void doit(Tokens t) {1772int cntTokens = t.countTokens();1773if (cntTokens > 2) {1774err.println("More than 2 options specified: " + cntTokens);1775usage();1776return;1777}1778JMap jmap = new JMap();1779String filename = "heap.bin";1780int gzlevel = 0;1781/*1782* Possible command:1783* dumpheap gz=1 file;1784* dumpheap gz=1;1785* dumpheap file;1786* dumpheap1787*1788* Use default filename if cntTokens == 0.1789* Handle cases with cntTokens == 1 or 2.1790*/1791if (cntTokens == 1) { // first argument could be filename or "gz="1792String option = t.nextToken();1793if (!option.startsWith("gz=")) {1794filename = option;1795} else {1796gzlevel = parseHeapDumpCompressionLevel(option);1797if (gzlevel == 0) {1798usage();1799return;1800}1801filename = "heap.bin.gz";1802}1803}1804if (cntTokens == 2) { // first argument is "gz=" followed by filename1805String option = t.nextToken();1806gzlevel = parseHeapDumpCompressionLevel(option);1807if (gzlevel == 0) {1808usage();1809return;1810}1811filename = t.nextToken();1812if (filename.startsWith("gz=")) {1813err.println("Filename should not start with \"gz=\": " + filename);1814usage();1815return;1816}1817}1818try {1819jmap.writeHeapHprofBin(filename, gzlevel);1820} catch (Exception e) {1821err.println("Error: " + e);1822if (verboseExceptions) {1823e.printStackTrace(err);1824}1825}1826}1827},1828new Command("class", "class name", false) {1829public void doit(Tokens t) {1830if (t.countTokens() != 1) {1831usage();1832return;1833}1834String classname = t.nextToken();1835InstanceKlass ik = SystemDictionaryHelper.findInstanceKlass(classname);1836if (ik == null) {1837out.println("class not found: " + classname);1838} else {1839out.println(ik.getName().asString() + " @" + ik.getAddress());1840}1841}1842},1843new Command("classes", "classes", false) {1844public void doit(Tokens t) {1845if (t.countTokens() != 0) {1846usage();1847return;1848}1849ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();1850cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {1851public void visit(Klass k) {1852out.println(k.getName().asString() + " @" + k.getAddress());1853}1854}1855);1856}1857},1858};18591860private boolean verboseExceptions = false;1861private ArrayList<String> history = new ArrayList<>();1862private HashMap<String, Command> commands = new HashMap<>();1863private boolean doEcho = false;18641865private Command findCommand(String key) {1866return (Command)commands.get(key);1867}18681869public void printPrompt() {1870out.print("hsdb> ");1871}18721873private DebuggerInterface debugger;1874private HotSpotAgent agent;1875private BufferedReader in;1876private PrintStream out;1877private PrintStream err;18781879// called before debuggee attach1880private void preAttach() {1881// nothing for now..1882}18831884// called after debuggee attach1885private void postAttach() {1886// nothing for now..1887}18881889public void setOutput(PrintStream o) {1890out = o;1891}18921893public void setErr(PrintStream e) {1894err = e;1895}18961897public CommandProcessor(DebuggerInterface debugger, BufferedReader in, PrintStream out, PrintStream err) {1898this.debugger = debugger;1899this.agent = debugger.getAgent();1900this.in = in;1901this.out = out;1902this.err = err;1903for (int i = 0; i < commandList.length; i++) {1904Command c = commandList[i];1905if (commands.get(c.name) != null) {1906throw new InternalError(c.name + " has multiple definitions");1907}1908commands.put(c.name, c);1909}1910if (debugger.isAttached()) {1911postAttach();1912}1913}191419151916public void run(boolean prompt) {1917// Process interactive commands.1918while (!quit) {1919if (prompt) printPrompt();1920String ln = null;1921try {1922ln = in.readLine();1923} catch (IOException e) {1924}1925if (ln == null) {1926if (prompt) err.println("Input stream closed.");1927return;1928}19291930executeCommand(ln, prompt);1931}1932}19331934static Pattern historyPattern = Pattern.compile("([\\\\]?)((!\\*)|(!\\$)|(!!-?)|(!-?[0-9][0-9]*)|(![a-zA-Z][^ ]*))");19351936public void executeCommand(String ln, boolean putInHistory) {1937if (ln.indexOf('!') != -1) {1938int size = history.size();1939if (size == 0) {1940ln = "";1941err.println("History is empty");1942} else {1943StringBuilder result = new StringBuilder();1944Matcher m = historyPattern.matcher(ln);1945int start = 0;1946while (m.find()) {1947// Capture the text preceding the matched text.1948if (m.start() > start) {1949result.append(ln.substring(start, m.start()));1950}1951start = m.end();19521953if (m.group(1).length() != 0) {1954// This means we matched a `\` before the '!'. Don't do any history1955// expansion in this case. Just capture what matched after the `\`.1956result.append(m.group(2));1957continue;1958}19591960String cmd = m.group(2);1961if (cmd.equals("!!")) {1962result.append((String)history.get(history.size() - 1));1963} else if (cmd.equals("!!-")) {1964Tokens item = new Tokens((String)history.get(history.size() - 1));1965item.trim(1);1966result.append(item.join(" "));1967} else if (cmd.equals("!*")) {1968Tokens item = new Tokens((String)history.get(history.size() - 1));1969item.nextToken();1970result.append(item.join(" "));1971} else if (cmd.equals("!$")) {1972Tokens item = new Tokens((String)history.get(history.size() - 1));1973result.append(item.at(item.countTokens() - 1));1974} else {1975String tail = cmd.substring(1);1976switch (tail.charAt(0)) {1977case '0':1978case '1':1979case '2':1980case '3':1981case '4':1982case '5':1983case '6':1984case '7':1985case '8':1986case '9':1987case '-': {1988int index = Integer.parseInt(tail);1989if (index < 0) {1990index = history.size() + index;1991}1992if (index > size) {1993err.println("No such history item");1994} else {1995result.append((String)history.get(index));1996}1997break;1998}1999default: {2000for (int i = history.size() - 1; i >= 0; i--) {2001String s = (String)history.get(i);2002if (s.startsWith(tail)) {2003result.append(s);2004break; // only capture the most recent match in the history2005}2006}2007}2008}2009}2010}2011if (result.length() == 0) {2012err.println("malformed history reference");2013ln = "";2014} else {2015if (start < ln.length()) {2016result.append(ln.substring(start));2017}2018ln = result.toString();2019if (!doEcho) {2020out.println(ln);2021}2022}2023}2024}20252026if (doEcho) {2027out.println("+ " + ln);2028}20292030PrintStream redirect = null;2031Tokens t = new Tokens(ln);2032if (t.hasMoreTokens()) {2033boolean error = false;2034if (putInHistory) history.add(ln);2035int len = t.countTokens();2036if (len > 2) {2037String r = t.at(len - 2);2038if (r.equals(">") || r.equals(">>")) {2039boolean append = r.length() == 2;2040String file = t.at(len - 1);2041try {2042redirect = new PrintStream(new BufferedOutputStream(new FileOutputStream(file, append)));2043t.trim(2);2044} catch (Exception e) {2045out.println("Error: " + e);2046if (verboseExceptions) {2047e.printStackTrace(out);2048}2049error = true;2050}2051}2052}2053if (!error) {2054PrintStream savedout = out;2055if (redirect != null) {2056out = redirect;2057}2058try {2059executeCommand(t);2060} catch (Exception e) {2061err.println("Error: " + e);2062if (verboseExceptions) {2063e.printStackTrace(err);2064}2065} finally {2066if (redirect != null) {2067out = savedout;2068redirect.close();2069}2070}2071}2072}2073}20742075void executeCommand(Tokens args) {2076String cmd = args.nextToken();20772078Command doit = findCommand(cmd);20792080/*2081* Check for an unknown command2082*/2083if (doit == null) {2084out.println("Unrecognized command. Try help...");2085} else if (!debugger.isAttached() && !doit.okIfDisconnected) {2086out.println("Command not valid until attached to a VM");2087} else {2088try {2089doit.doit(args);2090} catch (Exception e) {2091out.println("Error: " + e);2092if (verboseExceptions) {2093e.printStackTrace(out);2094}2095}2096}2097}20982099/* Parse compression level2100* @return 1-9 compression level2101* 0 compression level is illegal2102*/2103private int parseHeapDumpCompressionLevel(String option) {21042105String[] keyValue = option.split("=");2106if (!keyValue[0].equals("gz")) {2107err.println("Expected option is \"gz=\"");2108return 0;2109}2110if (keyValue.length != 2) {2111err.println("Exactly one argument is expected for option \"gz\"");2112return 0;2113}2114int gzl = 0;2115String level = keyValue[1];2116try {2117gzl = Integer.parseInt(level);2118} catch (NumberFormatException e) {2119err.println("gz option value not an integer ("+level+")");2120return 0;2121}2122if (gzl < 1 || gzl > 9) {2123err.println("Compression level out of range (1-9): " + level);2124return 0;2125}2126return gzl;2127}2128}212921302131