< prev index next >

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java

Print this page




   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;
  26 



  27 import java.io.BufferedOutputStream;
  28 import java.io.BufferedReader;
  29 import java.io.ByteArrayOutputStream;
  30 import java.io.FileInputStream;
  31 import java.io.FileOutputStream;
  32 import java.io.IOException;
  33 import java.io.InputStreamReader;
  34 import java.io.PrintStream;
  35 import java.util.ArrayList;
  36 import java.util.Arrays;

  37 import java.util.Comparator;
  38 import java.util.HashMap;
  39 import java.util.HashSet;
  40 import java.util.Iterator;


  41 import java.util.Stack;

  42 import java.util.regex.Matcher;
  43 import java.util.regex.Pattern;
  44 


  45 import sun.jvm.hotspot.ci.ciEnv;
  46 import sun.jvm.hotspot.code.CodeBlob;
  47 import sun.jvm.hotspot.code.CodeCacheVisitor;
  48 import sun.jvm.hotspot.code.NMethod;
  49 import sun.jvm.hotspot.debugger.Address;
  50 import sun.jvm.hotspot.debugger.OopHandle;
  51 import sun.jvm.hotspot.classfile.ClassLoaderDataGraph;
  52 import sun.jvm.hotspot.memory.FileMapInfo;
  53 import sun.jvm.hotspot.memory.SystemDictionary;
  54 import sun.jvm.hotspot.memory.Universe;
  55 import sun.jvm.hotspot.gc.shared.CollectedHeap;
  56 import sun.jvm.hotspot.gc.g1.G1CollectedHeap;
  57 import sun.jvm.hotspot.oops.DefaultHeapVisitor;
  58 import sun.jvm.hotspot.oops.HeapVisitor;
  59 import sun.jvm.hotspot.oops.InstanceKlass;
  60 import sun.jvm.hotspot.oops.Klass;
  61 import sun.jvm.hotspot.oops.Metadata;
  62 import sun.jvm.hotspot.oops.Method;
  63 import sun.jvm.hotspot.oops.MethodData;
  64 import sun.jvm.hotspot.oops.Oop;


 121         public boolean canInclude(InstanceKlass kls) {
 122             return kls.getClassLoader() == null;
 123         }
 124     }
 125 
 126     public static class NonBootFilter implements ClassFilter {
 127         private HashMap emitted = new HashMap();
 128         public boolean canInclude(InstanceKlass kls) {
 129             if (kls.getClassLoader() == null) return false;
 130             if (emitted.get(kls.getName()) != null) {
 131                 // Since multiple class loaders are being shoved
 132                 // together duplicate classes are a possibilty.  For
 133                 // now just ignore them.
 134                 return false;
 135             }
 136             emitted.put(kls.getName(), kls);
 137             return true;
 138         }
 139     }
 140 
 141     static class Tokens {
 142         final String input;
 143         int i;
 144         String[] tokens;
 145         int length;
 146 
 147         String[] splitWhitespace(String cmd) {
 148             String[] t = cmd.split("\\s");
 149             if (t.length == 1 && t[0].length() == 0) {
 150                 return new String[0];
 151             }
 152             return t;
 153         }
 154 
 155         void add(String s, ArrayList t) {
 156             if (s.length() > 0) {
 157                 t.add(s);
 158             }
 159         }
 160 
 161         Tokens(String cmd) {
 162             input = cmd;
 163 
 164             // check for quoting
 165             int quote = cmd.indexOf('"');
 166             ArrayList t = new ArrayList();
 167             if (quote != -1) {
 168                 while (cmd.length() > 0) {
 169                     if (quote != -1) {
 170                         int endquote = cmd.indexOf('"', quote + 1);
 171                         if (endquote == -1) {
 172                             throw new RuntimeException("mismatched quotes: " + input);
 173                         }
 174 
 175                         String before = cmd.substring(0, quote).trim();
 176                         String quoted = cmd.substring(quote + 1, endquote);
 177                         cmd = cmd.substring(endquote + 1).trim();
 178                         if (before.length() > 0) {
 179                             String[] w = splitWhitespace(before);
 180                             for (int i = 0; i < w.length; i++) {
 181                                 add(w[i], t);
 182                             }
 183                         }
 184                         add(quoted, t);
 185                         quote = cmd.indexOf('"');
 186                     } else {
 187                         String[] w = splitWhitespace(cmd);
 188                         for (int i = 0; i < w.length; i++) {
 189                             add(w[i], t);
 190                         }
 191                         cmd = "";
 192 
 193                     }
 194                 }
 195             } else {
 196                 String[] w = splitWhitespace(cmd);
 197                 for (int i = 0; i < w.length; i++) {
 198                     add(w[i], t);
 199                 }
 200             }
 201             tokens = (String[])t.toArray(new String[0]);
 202             i = 0;
 203             length = tokens.length;
 204 
 205             //for (int i = 0; i < tokens.length; i++) {
 206             //    System.out.println("\"" + tokens[i] + "\"");
 207             //}
 208         }
 209 
 210         String nextToken() {
 211             return tokens[i++];
 212         }
 213         boolean hasMoreTokens() {
 214             return i < length;
 215         }
 216         int countTokens() {
 217             return length - i;
 218         }
 219         void trim(int n) {
 220             if (length >= n) {
 221                 length -= n;
 222             } else {
 223                 throw new IndexOutOfBoundsException(String.valueOf(n));
 224             }
 225         }
 226         String join(String sep) {
 227             StringBuffer result = new StringBuffer();
 228             for (int w = i; w < length; w++) {
 229                 result.append(tokens[w]);
 230                 if (w + 1 < length) {
 231                     result.append(sep);
 232                 }
 233             }
 234             return result.toString();
 235         }
 236 
 237         String at(int i) {
 238             if (i < 0 || i >= length) {
 239                 throw new IndexOutOfBoundsException(String.valueOf(i));
 240             }
 241             return tokens[i];
 242         }
 243     }
 244 
 245 
 246     abstract class Command {
 247         Command(String n, String u, boolean ok) {
 248             name = n;
 249             usage = u;
 250             okIfDisconnected = ok;
 251         }
 252 
 253         Command(String n, boolean ok) {
 254             name = n;
 255             usage = n;
 256             okIfDisconnected = ok;
 257         }
 258 
 259         final String name;
 260         final String usage;
 261         final boolean okIfDisconnected;
 262         abstract void doit(Tokens t);
 263         void usage() {
 264             out.println("Usage: " + usage);











 265         }
 266 



 267         void printOopValue(Oop oop) {
 268             if (oop != null) {
 269                 Klass k = oop.getKlass();
 270                 Symbol s = k.getName();
 271                 if (s != null) {
 272                     out.print("Oop for " + s.asString() + " @ ");
 273                 } else {
 274                     out.print("Oop @ ");
 275                 }
 276                 Oop.printOopAddressOn(oop, out);
 277             } else {
 278                 out.print("null");
 279             }
 280         }
 281 
 282         void printNode(SimpleTreeNode node) {
 283             int count = node.getChildCount();
 284             for (int i = 0; i < count; i++) {
 285                 try {
 286                     SimpleTreeNode field = node.getChild(i);


 373             for (int i = 0; i < parts.length; i++) {
 374                 int len = parts[i].length();
 375                 if (len >= 26) {
 376                     mangled.append((char)('a' + (len / 26)));
 377                     len = len % 26;
 378                 }
 379                 mangled.append((char)('A' + len));
 380                 mangled.append(parts[i]);
 381             }
 382             mangled.append("_");
 383             symbol = mangled.toString();
 384         }
 385         return VM.getVM().getDebugger().lookup(null, symbol);
 386     }
 387 
 388     Address parseAddress(String addr) {
 389         return VM.getVM().getDebugger().parseAddress(addr);
 390     }
 391 
 392     private final Command[] commandList = {
 393         new Command("reattach", true) {
 394             public void doit(Tokens t) {

 395                 int tokens = t.countTokens();
 396                 if (tokens != 0) {
 397                     usage();
 398                     return;
 399                 }
 400                 preAttach();
 401                 debugger.reattach();
 402                 postAttach();
 403             }
 404         },
 405         new Command("attach", "attach pid | exec core", true) {
 406             public void doit(Tokens t) {

 407                 int tokens = t.countTokens();
 408                 if (tokens == 1) {
 409                     preAttach();
 410                     debugger.attach(t.nextToken());
 411                     postAttach();
 412                 } else if (tokens == 2) {
 413                     preAttach();
 414                     debugger.attach(t.nextToken(), t.nextToken());
 415                     postAttach();
 416                 } else {
 417                     usage();
 418                 }
 419             }
 420         },
 421         new Command("detach", false) {
 422             public void doit(Tokens t) {

 423                 if (t.countTokens() != 0) {
 424                     usage();
 425                 } else {
 426                     debugger.detach();
 427                 }
 428             }
 429         },
 430         new Command("examine", "examine [ address/count ] | [ address,address]", false) {
 431             Pattern args1 = Pattern.compile("^(0x[0-9a-f]+)(/([0-9]*)([a-z]*))?$");
 432             Pattern args2 = Pattern.compile("^(0x[0-9a-f]+),(0x[0-9a-f]+)(/[a-z]*)?$");
 433 
 434             String fill(Address a, int width) {
 435                 String s = "0x0";
 436                 if (a != null) {
 437                     s = a.toString();
 438                 }
 439                 if (s.length() != width) {
 440                     return s.substring(0, 2) + "000000000000000000000".substring(0, width - s.length()) + s.substring(2);
 441                 }
 442                 return s;
 443             }
 444 
 445             public void doit(Tokens t) {

 446                 if (t.countTokens() != 1) {
 447                     usage();
 448                 } else {
 449                     String arg = t.nextToken();
 450                     Matcher m1 = args1.matcher(arg);
 451                     Matcher m2 = args2.matcher(arg);
 452                     Address start = null;
 453                     Address end   = null;
 454                     String format = "";
 455                     int formatSize = (int)VM.getVM().getAddressSize();
 456 
 457                     if (m1.matches()) {
 458                         start = VM.getVM().getDebugger().parseAddress(m1.group(1));
 459                         int count = 1;
 460                         if (m1.group(2) != null) {
 461                             count = Integer.parseInt(m1.group(3));
 462                         }
 463                         end = start.addOffsetTo(count * formatSize);
 464                     } else if (m2.matches()) {
 465                         start = VM.getVM().getDebugger().parseAddress(m2.group(1));


 484                         start = start.addOffsetTo(formatSize);
 485                         if (width <= formatWidth) {
 486                             out.println();
 487                             needsPrintln = false;
 488                             if (start.lessThan(end)) {
 489                                 out.print(fill(start, formatWidth));
 490                                 out.print(": ");
 491                                 width = line - formatWidth - 2;
 492                             }
 493                         } else {
 494                             out.print(" ");
 495                             width -= 1;
 496                         }
 497                     }
 498                     if (needsPrintln) {
 499                         out.println();
 500                     }
 501                 }
 502             }
 503         },
 504         new Command("dumpreplaydata", "dumpreplaydata { <address > | -a | <thread_id> }", false) {
 505             // This is used to dump replay data from ciInstanceKlass, ciMethodData etc
 506             // default file name is replay.txt, also if java crashes in compiler
 507             // thread, this file will be dumped in error processing.
 508             public void doit(Tokens t) {

 509                 if (t.countTokens() != 1) {
 510                     usage();
 511                     return;
 512                 }
 513                 String name = t.nextToken();
 514                 Address a = null;
 515                 try {
 516                     a = VM.getVM().getDebugger().parseAddress(name);
 517                 } catch (NumberFormatException e) { }
 518                 if (a != null) {
 519                     // only nmethod, Method, MethodData and InstanceKlass needed to
 520                     // dump replay data
 521 
 522                     CodeBlob cb = VM.getVM().getCodeCache().findBlob(a);
 523                     if (cb != null && (cb instanceof NMethod)) {
 524                         ((NMethod)cb).dumpReplayData(out);
 525                         return;
 526                     }
 527                     // assume it is Metadata
 528                     Metadata meta = Metadata.instantiateWrapperFor(a);


 535                 }
 536                 // Not an address
 537                 boolean all = name.equals("-a");
 538                 Threads threads = VM.getVM().getThreads();
 539                 for (int i = 0; i < threads.getNumberOfThreads(); i++) {
 540                     JavaThread thread = threads.getJavaThreadAt(i);
 541                     ByteArrayOutputStream bos = new ByteArrayOutputStream();
 542                     thread.printThreadIDOn(new PrintStream(bos));
 543                     if (all || bos.toString().equals(name)) {
 544                         if (thread instanceof CompilerThread) {
 545                             CompilerThread ct = (CompilerThread)thread;
 546                             ciEnv env = ct.env();
 547                             if (env != null) {
 548                                env.dumpReplayData(out);
 549                             }
 550                         }
 551                     }
 552                 }
 553             }
 554         },
 555         new Command("buildreplayjars", "buildreplayjars [ all | app | boot ]  | [ prefix ]", false) {
 556             // This is used to dump jar files of all the classes
 557             // loaded in the core.  Everything with null classloader
 558             // will go in boot.jar and everything else will go in
 559             // app.jar. boot.jar usually not needed, unless changed by jvmti.
 560             public void doit(Tokens t) {

 561                 int tcount = t.countTokens();
 562                 if (tcount > 2) {
 563                     usage();
 564                     return;
 565                 }
 566                 try {
 567                    String prefix = "";
 568                    String option = "all"; // default
 569                    switch(tcount) {
 570                        case 0:
 571                            break;
 572                        case 1:
 573                            option = t.nextToken();
 574                            if (!option.equalsIgnoreCase("all") && !option.equalsIgnoreCase("app") &&
 575                                !option.equalsIgnoreCase("root")) {
 576                               prefix = option;
 577                               option = "all";
 578                            }
 579                            break;
 580                        case 2:


 589                                !option.equalsIgnoreCase("boot")) {
 590                        usage();
 591                        return;
 592                    }
 593                    ClassDump cd = new ClassDump();
 594                    if (option.equalsIgnoreCase("all") || option.equalsIgnoreCase("boot")) {
 595                      cd.setClassFilter(new BootFilter());
 596                      cd.setJarOutput(prefix + "boot.jar");
 597                      cd.run();
 598                    }
 599                    if (option.equalsIgnoreCase("all") || option.equalsIgnoreCase("app")) {
 600                      cd.setClassFilter(new NonBootFilter());
 601                      cd.setJarOutput(prefix + "app.jar");
 602                      cd.run();
 603                    }
 604                 } catch (IOException ioe) {
 605                    ioe.printStackTrace();
 606                 }
 607             }
 608         },
 609         new Command("findpc", "findpc address", false) {
 610             public void doit(Tokens t) {

 611                 if (t.countTokens() != 1) {
 612                     usage();
 613                 } else {
 614                     Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
 615                     PointerLocation loc = PointerFinder.find(a);
 616                     loc.printOn(out);
 617                 }
 618             }
 619         },
 620         new Command("symbol", "symbol address", false) {
 621             public void doit(Tokens t) {

 622                 if (t.countTokens() != 1) {
 623                     usage();
 624                 } else {
 625                     Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
 626                     Symbol.create(a).printValueOn(out);
 627                     out.println();
 628                 }
 629             }
 630         },
 631         new Command("flags", "flags [ flag | -nd ]", false) {
 632             public void doit(Tokens t) {

 633                 int tokens = t.countTokens();
 634                 if (tokens != 0 && tokens != 1) {
 635                     usage();
 636                 } else {
 637                     String name = tokens > 0 ? t.nextToken() : null;
 638                     boolean nonDefault = false;
 639                     if (name != null && name.equals("-nd")) {
 640                         name = null;
 641                         nonDefault = true;
 642                     }
 643 
 644                     VM.Flag[] flags = VM.getVM().getCommandLineFlags();
 645                     if (flags == null) {
 646                         out.println("Command Flag info not available (use 1.4.1_03 or later)!");
 647                     } else {
 648                         boolean printed = false;
 649                         for (int f = 0; f < flags.length; f++) {
 650                             VM.Flag flag = flags[f];
 651                             if (name == null || flag.getName().equals(name)) {
 652 
 653                                 if (nonDefault && (flag.getOrigin() == VM.Flags_DEFAULT)) {
 654                                     // only print flags which aren't their defaults
 655                                     continue;
 656                                 }
 657                                 out.println(flag.getName() + " = " + flag.getValue() + " " + flag.getOriginString());
 658                                 printed = true;
 659                             }
 660                         }
 661                         if (name != null && !printed) {
 662                             out.println("Couldn't find flag: " + name);
 663                         }
 664                     }
 665                 }
 666             }
 667         },
 668         new Command("help", "help [ command ]", true) {
 669             public void doit(Tokens t) {

 670                 int tokens = t.countTokens();
 671                 Command cmd = null;
 672                 if (tokens == 1) {
 673                     cmd = findCommand(t.nextToken());
 674                 }
 675 
 676                 if (cmd != null) {
 677                     cmd.usage();
 678                 } else if (tokens == 0) {
 679                     out.println("Available commands:");
 680                     Object[] keys = commands.keySet().toArray();
 681                     Arrays.sort(keys, new Comparator() {
 682                              public int compare(Object o1, Object o2) {
 683                                  return o1.toString().compareTo(o2.toString());
 684                              }
 685                           });
 686                     for (int i = 0; i < keys.length; i++) {
 687                         out.print("  ");
 688                         out.println(((Command)commands.get(keys[i])).usage);
 689                     }
 690                 }
 691             }
 692         },
 693         new Command("history", "history", true) {
 694             public void doit(Tokens t) {

 695                 int tokens = t.countTokens();
 696                 if (tokens != 0 && (tokens != 1 || !t.nextToken().equals("-h"))) {
 697                     usage();
 698                     return;
 699                 }
 700                 boolean printIndex = tokens == 0;
 701                 for (int i = 0; i < history.size(); i++) {
 702                     if (printIndex) out.print(i + " ");
 703                     out.println(history.get(i));
 704                 }
 705             }
 706         },
 707         // decode raw address
 708         new Command("dis", "dis address [length]", false) {
 709             public void doit(Tokens t) {

 710                 int tokens = t.countTokens();
 711                 if (tokens != 1 && tokens != 2) {
 712                     usage();
 713                     return;
 714                 }
 715                 String name = t.nextToken();
 716                 Address addr = null;
 717                 int len = 0x10; // default length
 718                 try {
 719                     addr = VM.getVM().getDebugger().parseAddress(name);
 720                 } catch (NumberFormatException e) {
 721                    out.println(e);
 722                    return;
 723                 }
 724                 if (tokens == 2) {
 725                     try {
 726                         len = Integer.parseInt(t.nextToken());
 727                     } catch (NumberFormatException e) {
 728                         out.println(e);
 729                         return;
 730                     }
 731                 }
 732                 HTMLGenerator generator = new HTMLGenerator(false);
 733                 out.println(generator.genHTMLForRawDisassembly(addr, len));
 734             }
 735 
 736         },
 737         // decode codeblob or nmethod
 738         new Command("disassemble", "disassemble address", false) {
 739             public void doit(Tokens t) {

 740                 int tokens = t.countTokens();
 741                 if (tokens != 1) {
 742                     usage();
 743                     return;
 744                 }
 745                 String name = t.nextToken();
 746                 Address addr = null;
 747                 try {
 748                     addr = VM.getVM().getDebugger().parseAddress(name);
 749                 } catch (NumberFormatException e) {
 750                    out.println(e);
 751                    return;
 752                 }
 753 
 754                 HTMLGenerator generator = new HTMLGenerator(false);
 755                 out.println(generator.genHTML(addr));
 756             }
 757         },
 758         // print Java bytecode disassembly
 759         new Command("jdis", "jdis address", false) {
 760             public void doit(Tokens t) {

 761                 int tokens = t.countTokens();
 762                 if (tokens != 1) {
 763                     usage();
 764                     return;
 765                 }
 766                 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
 767                 Method m = (Method)Metadata.instantiateWrapperFor(a);
 768                 HTMLGenerator html = new HTMLGenerator(false);
 769                 out.println(html.genHTML(m));
 770             }
 771         },
 772         new Command("revptrs", "revptrs address", false) {
 773             public void doit(Tokens t) {

 774                 int tokens = t.countTokens();
 775                 if (tokens != 1 && (tokens != 2 || !t.nextToken().equals("-c"))) {
 776                     usage();
 777                     return;
 778                 }
 779                 boolean chase = tokens == 2;
 780                 ReversePtrs revptrs = VM.getVM().getRevPtrs();
 781                 if (revptrs == null) {
 782                     out.println("Computing reverse pointers...");
 783                     ReversePtrsAnalysis analysis = new ReversePtrsAnalysis();
 784                     final boolean[] complete = new boolean[1];
 785                     HeapProgressThunk thunk = new HeapProgressThunk() {
 786                             public void heapIterationFractionUpdate(double d) {}
 787                             public synchronized void heapIterationComplete() {
 788                                 complete[0] = true;
 789                                 notify();
 790                             }
 791                         };
 792                     analysis.setHeapProgressThunk(thunk);
 793                     analysis.run();


 814                             while (ptrs.size() == 1) {
 815                                 LivenessPathElement e = (LivenessPathElement)ptrs.get(0);
 816                                 ByteArrayOutputStream bos = new ByteArrayOutputStream();
 817                                 Oop.printOopValueOn(e.getObj(), new PrintStream(bos));
 818                                 out.println(bos.toString());
 819                                 ptrs = revptrs.get(e.getObj());
 820                             }
 821                         } else {
 822                             for (int i = 0; i < ptrs.size(); i++) {
 823                                 LivenessPathElement e = (LivenessPathElement)ptrs.get(i);
 824                                 ByteArrayOutputStream bos = new ByteArrayOutputStream();
 825                                 Oop.printOopValueOn(e.getObj(), new PrintStream(bos));
 826                                 out.println(bos.toString());
 827                                 oop = e.getObj();
 828                             }
 829                         }
 830                     }
 831                 }
 832             }
 833         },
 834         new Command("printmdo", "printmdo [ -a | expression ]", false) {
 835             // Print every MDO in the heap or the one referenced by expression.
 836             public void doit(Tokens t) {

 837                 if (t.countTokens() != 1) {
 838                     usage();
 839                 } else {
 840                     String s = t.nextToken();
 841                     if (s.equals("-a")) {
 842                         ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
 843                         cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
 844                                 public void visit(Klass k) {
 845                                     if (k instanceof InstanceKlass) {
 846                                         MethodArray methods = ((InstanceKlass)k).getMethods();
 847                                         for (int i = 0; i < methods.length(); i++) {
 848                                             Method m = methods.at(i);
 849                                             MethodData mdo = m.getMethodData();
 850                                             if (mdo != null) {
 851                                                 out.println("MethodData " + mdo.getAddress() + " for " +
 852                                                     "method " + m.getMethodHolder().getName().asString() + "." +
 853                                                     m.getName().asString() +
 854                                                             m.getSignature().asString() + "@" + m.getAddress());
 855                                                 mdo.printDataOn(out);
 856                                     }
 857                                 }
 858                                     }
 859                                 }
 860                             }
 861                             );
 862                     } else {
 863                         Address a = VM.getVM().getDebugger().parseAddress(s);
 864                         MethodData mdo = (MethodData) Metadata.instantiateWrapperFor(a);
 865                         mdo.printDataOn(out);
 866                     }
 867                 }
 868             }
 869         },
 870         new Command("printall", "printall", false) {
 871             // Print every MDO in the heap or the one referenced by expression.
 872             public void doit(Tokens t) {

 873                 if (t.countTokens() != 0) {
 874                     usage();
 875                 } else {
 876                     ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
 877                     cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
 878                             public void visit(Klass k) {
 879                                 if (k instanceof InstanceKlass && ((InstanceKlass)k).getConstants().getCache() != null) {
 880                                     MethodArray methods = ((InstanceKlass)k).getMethods();
 881                                     for (int i = 0; i < methods.length(); i++) {
 882                                         Method m = methods.at(i);
 883                                         HTMLGenerator gen = new HTMLGenerator(false);
 884                                         out.println(gen.genHTML(m));
 885                                     }
 886                                 }
 887                             }
 888                         }
 889                         );
 890                 }
 891             }
 892         },
 893         new Command("dumpideal", "dumpideal { -a | id }", false) {
 894             // Do a full dump of the nodes reachabile from root in each compiler thread.
 895             public void doit(Tokens t) {

 896                 if (t.countTokens() != 1) {
 897                     usage();
 898                 } else {
 899                     String name = t.nextToken();
 900                     boolean all = name.equals("-a");
 901                     Threads threads = VM.getVM().getThreads();
 902                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
 903                         JavaThread thread = threads.getJavaThreadAt(i);
 904                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
 905                         thread.printThreadIDOn(new PrintStream(bos));
 906                         if (all || bos.toString().equals(name)) {
 907                           if (thread instanceof CompilerThread) {
 908                             CompilerThread ct = (CompilerThread)thread;
 909                             out.println(ct);
 910                             ciEnv env = ct.env();
 911                             if (env != null) {
 912                               Compile c = env.compilerData();
 913                               c.root().dump(9999, out);
 914                             } else {
 915                               out.println("  not compiling");
 916                             }
 917                           }
 918                         }
 919                     }
 920                 }
 921             }
 922         },
 923         new Command("dumpcfg", "dumpcfg { -a | id }", false) {
 924             // Dump the PhaseCFG for every compiler thread that has one live.
 925             public void doit(Tokens t) {

 926                 if (t.countTokens() != 1) {
 927                     usage();
 928                 } else {
 929                     String name = t.nextToken();
 930                     boolean all = name.equals("-a");
 931                     Threads threads = VM.getVM().getThreads();
 932                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
 933                         JavaThread thread = threads.getJavaThreadAt(i);
 934                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
 935                         thread.printThreadIDOn(new PrintStream(bos));
 936                         if (all || bos.toString().equals(name)) {
 937                           if (thread instanceof CompilerThread) {
 938                             CompilerThread ct = (CompilerThread)thread;
 939                             out.println(ct);
 940                             ciEnv env = ct.env();
 941                             if (env != null) {
 942                               Compile c = env.compilerData();
 943                               c.cfg().dump(out);
 944                             }
 945                           }
 946                         }
 947                     }
 948                 }
 949             }
 950         },
 951         new Command("dumpilt", "dumpilt { -a | id }", false) {
 952             // dumps the InlineTree of a C2 compile
 953             public void doit(Tokens t) {

 954                 if (t.countTokens() != 1) {
 955                     usage();
 956                 } else {
 957                     String name = t.nextToken();
 958                     boolean all = name.equals("-a");
 959                     Threads threads = VM.getVM().getThreads();
 960                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
 961                         JavaThread thread = threads.getJavaThreadAt(i);
 962                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
 963                         thread.printThreadIDOn(new PrintStream(bos));
 964                         if (all || bos.toString().equals(name)) {
 965                             if (thread instanceof CompilerThread) {
 966                                 CompilerThread ct = (CompilerThread)thread;
 967                                 ciEnv env = ct.env();
 968                                 if (env != null) {
 969                                     Compile c = env.compilerData();
 970                                     InlineTree ilt = c.ilt();
 971                                     if (ilt != null) {
 972                                         ilt.print(out);
 973                                     }
 974                                 }
 975                             }
 976                         }
 977                     }
 978                 }
 979             }
 980         },
 981         new Command("vmstructsdump", "vmstructsdump", false) {
 982             public void doit(Tokens t) {

 983                 if (t.countTokens() != 0) {
 984                     usage();
 985                     return;
 986                 }
 987 
 988                 // Dump a copy of the type database in a form that can
 989                 // be read back.
 990                 Iterator i = agent.getTypeDataBase().getTypes();
 991                 // Make sure the types are emitted in an order than can be read back in
 992                 HashSet emitted = new HashSet();
 993                 Stack pending = new Stack();
 994                 while (i.hasNext()) {
 995                     Type n = (Type)i.next();
 996                     if (emitted.contains(n.getName())) {
 997                         continue;
 998                     }
 999 
1000                     while (n != null && !emitted.contains(n.getName())) {
1001                         pending.push(n);
1002                         n = n.getSuperclass();
1003                     }
1004                     while (!pending.empty()) {
1005                         n = (Type)pending.pop();
1006                         dumpType(n);
1007                         emitted.add(n.getName());
1008                     }
1009                 }
1010                 i = agent.getTypeDataBase().getTypes();
1011                 while (i.hasNext()) {
1012                     dumpFields((Type)i.next(), false);
1013                 }
1014             }
1015         },
1016 
1017         new Command("inspect", "inspect expression", false) {
1018             public void doit(Tokens t) {

1019                 if (t.countTokens() != 1) {
1020                     usage();
1021                 } else {
1022                     Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
1023                     SimpleTreeNode node = null;
1024                     if (VM.getVM().getUniverse().heap().isInReserved(a)) {
1025                         OopHandle handle = a.addOffsetToAsOopHandle(0);
1026                         Oop oop = VM.getVM().getObjectHeap().newOop(handle);
1027                         node = new OopTreeNodeAdapter(oop, null);
1028 
1029                         out.println("instance of " + node.getValue() + " @ " + a +
1030                                     " (size = " + oop.getObjectSize() + ")");
1031                     } else if (VM.getVM().getCodeCache().contains(a)) {
1032                         CodeBlob blob = VM.getVM().getCodeCache().findBlobUnsafe(a);
1033                         a = blob.headerBegin();
1034                     }
1035                     if (node == null) {
1036                         Type type = VM.getVM().getTypeDataBase().guessTypeForAddress(a);
1037                         if (type == null && VM.getVM().isSharingEnabled()) {
1038                             // Check if the value falls in the _md_region
1039                             Address loc1 = a.getAddressAt(0);
1040                             FileMapInfo cdsFileMapInfo = VM.getVM().getFileMapInfo();
1041                             if (cdsFileMapInfo.inCopiedVtableSpace(loc1)) {
1042                                type = cdsFileMapInfo.getTypeForVptrAddress(loc1);
1043                             }
1044 
1045                         }
1046                         if (type != null) {
1047                             out.println("Type is " + type.getName() + " (size of " + type.getSize() + ")");
1048                             node = new CTypeTreeNodeAdapter(a, type, null);
1049                         }
1050                     }
1051                     if (node != null) {
1052                         printNode(node);
1053                     }
1054                 }
1055             }
1056         },
1057         new Command("jhisto", "jhisto", false) {
1058             public void doit(Tokens t) {

1059                  ObjectHistogram histo = new ObjectHistogram();
1060                  histo.run(out, err);
1061             }
1062         },
1063         new Command("jstack", "jstack [-v]", false) {
1064             public void doit(Tokens t) {

1065                 boolean verbose = false;
1066                 if (t.countTokens() > 0 && t.nextToken().equals("-v")) {
1067                     verbose = true;
1068                 }
1069                 StackTrace jstack = new StackTrace(verbose, true);
1070                 jstack.run(out);
1071             }
1072         },
1073         new Command("print", "print expression", false) {
1074             public void doit(Tokens t) {

1075                 if (t.countTokens() != 1) {
1076                     usage();
1077                 } else {
1078                     Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
1079                     HTMLGenerator gen = new HTMLGenerator(false);
1080                     out.println(gen.genHTML(a));
1081                 }
1082             }
1083         },
1084         new Command("printas", "printas type expression", false) {
1085             public void doit(Tokens t) {

1086                 if (t.countTokens() != 2) {
1087                     usage();
1088                 } else {
1089                     Type type = agent.getTypeDataBase().lookupType(t.nextToken());
1090                     Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
1091                     CTypeTreeNodeAdapter node = new CTypeTreeNodeAdapter(a, type, null);
1092 
1093                     out.println("pointer to " + type + " @ " + a +
1094                                 " (size = " + type.getSize() + ")");
1095                     printNode(node);
1096                 }
1097             }
1098         },
1099         new Command("printstatics", "printstatics [ type ]", false) {
1100             public void doit(Tokens t) {

1101                 if (t.countTokens() > 1) {
1102                     usage();
1103                 } else {
1104                     if (t.countTokens() == 0) {
1105                         out.println("All known static fields");
1106                         printNode(new CTypeTreeNodeAdapter(agent.getTypeDataBase().getTypes()));
1107                     } else {
1108                         Type type = agent.getTypeDataBase().lookupType(t.nextToken());
1109                         out.println("Static fields of " + type.getName());
1110                         printNode(new CTypeTreeNodeAdapter(type));
1111                     }
1112                 }
1113             }
1114         },
1115         new Command("pmap", "pmap", false) {
1116             public void doit(Tokens t) {

1117                 PMap pmap = new PMap();
1118                 pmap.run(out, debugger.getAgent().getDebugger());
1119             }
1120         },
1121         new Command("pstack", "pstack [-v]", false) {
1122             public void doit(Tokens t) {

1123                 boolean verbose = false;
1124                 if (t.countTokens() > 0 && t.nextToken().equals("-v")) {
1125                     verbose = true;
1126                 }
1127                 PStack pstack = new PStack(verbose, true);
1128                 pstack.run(out, debugger.getAgent().getDebugger());
1129             }
1130         },
1131         new Command("quit", true) {
1132             public void doit(Tokens t) {

1133                 if (t.countTokens() != 0) {
1134                     usage();
1135                 } else {
1136                     debugger.detach();
1137                     quit = true;
1138                 }
1139             }
1140         },
1141         new Command("echo", "echo [ true | false ]", true) {
1142             public void doit(Tokens t) {

1143                 if (t.countTokens() == 0) {
1144                     out.println("echo is " + doEcho);
1145                 } else if (t.countTokens() == 1) {
1146                     doEcho = Boolean.valueOf(t.nextToken()).booleanValue();
1147                 } else {
1148                     usage();
1149                 }
1150             }
1151         },
1152         new Command("versioncheck", "versioncheck [ true | false ]", true) {
1153             public void doit(Tokens t) {

1154                 if (t.countTokens() == 0) {
1155                     out.println("versioncheck is " +
1156                                 (System.getProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck") == null));
1157                 } else if (t.countTokens() == 1) {
1158                     if (Boolean.valueOf(t.nextToken()).booleanValue()) {
1159                         System.setProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck", null);
1160                     } else {
1161                         System.setProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck", "true");
1162                     }
1163                 } else {
1164                     usage();
1165                 }
1166             }
1167         },
1168         new Command("scanoops", "scanoops start end [ type ]", false) {
1169             public void doit(Tokens t) {

1170                 if (t.countTokens() != 2 && t.countTokens() != 3) {
1171                     usage();
1172                 } else {
1173                     long stride = VM.getVM().getAddressSize();
1174                     Address base = VM.getVM().getDebugger().parseAddress(t.nextToken());
1175                     Address end  = VM.getVM().getDebugger().parseAddress(t.nextToken());
1176                     Klass klass = null;
1177                     if (t.countTokens() == 1) {
1178                         klass = SystemDictionaryHelper.findInstanceKlass(t.nextToken());
1179                         if (klass == null) {
1180                             out.println("No such type.");
1181                             return;
1182                         }
1183                     }
1184                     while (base != null && base.lessThan(end)) {
1185                         long step = stride;
1186                         OopHandle handle = base.addOffsetToAsOopHandle(0);
1187                         if (RobustOopDeterminator.oopLooksValid(handle)) {
1188                             try {
1189                                 Oop oop = VM.getVM().getObjectHeap().newOop(handle);
1190                                 if (klass == null || oop.getKlass().isSubtypeOf(klass))
1191                                     out.println(handle.toString() + " " + oop.getKlass().getName().asString());
1192                                 step = oop.getObjectSize();
1193                             } catch (UnknownOopException ex) {
1194                                 // ok
1195                             } catch (RuntimeException ex) {
1196                                 ex.printStackTrace();
1197                             }
1198                         }
1199                         base = base.addOffsetTo(step);
1200                     }
1201                 }
1202             }
1203         },
1204         new Command("intConstant", "intConstant [ name [ value ] ]", true) {
1205             public void doit(Tokens t) {

1206                 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 2) {
1207                     usage();
1208                     return;
1209                 }
1210                 HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();
1211                 if (t.countTokens() == 1) {
1212                     String name = t.nextToken();
1213                     out.println("intConstant " + name + " " + db.lookupIntConstant(name));
1214                 } else if (t.countTokens() == 0) {
1215                     Iterator i = db.getIntConstants();
1216                     while (i.hasNext()) {
1217                         String name = (String)i.next();
1218                         out.println("intConstant " + name + " " + db.lookupIntConstant(name));
1219                     }
1220                 } else if (t.countTokens() == 2) {
1221                     String name = t.nextToken();
1222                     Integer value = Integer.valueOf(t.nextToken());
1223                     db.addIntConstant(name, value);
1224                 }
1225             }
1226         },
1227         new Command("longConstant", "longConstant [ name [ value ] ]", true) {
1228             public void doit(Tokens t) {

1229                 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 2) {
1230                     usage();
1231                     return;
1232                 }
1233                 HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();
1234                 if (t.countTokens() == 1) {
1235                     String name = t.nextToken();
1236                     out.println("longConstant " + name + " " + db.lookupLongConstant(name));
1237                 } else if (t.countTokens() == 0) {
1238                     Iterator i = db.getLongConstants();
1239                     while (i.hasNext()) {
1240                         String name = (String)i.next();
1241                         out.println("longConstant " + name + " " + db.lookupLongConstant(name));
1242                     }
1243                 } else if (t.countTokens() == 2) {
1244                     String name = t.nextToken();
1245                     Long value = Long.valueOf(t.nextToken());
1246                     db.addLongConstant(name, value);
1247                 }
1248             }
1249         },
1250         new Command("field", "field [ type [ name fieldtype isStatic offset address ] ]", true) {
1251             public void doit(Tokens t) {

1252                 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) {
1253                     usage();
1254                     return;
1255                 }
1256                 if (t.countTokens() == 1) {
1257                     Type type = agent.getTypeDataBase().lookupType(t.nextToken());
1258                     dumpFields(type);
1259                 } else if (t.countTokens() == 0) {
1260                     Iterator i = agent.getTypeDataBase().getTypes();
1261                     while (i.hasNext()) {
1262                         dumpFields((Type)i.next());
1263                     }
1264                 } else {
1265                     BasicType containingType = (BasicType)agent.getTypeDataBase().lookupType(t.nextToken());
1266 
1267                     String fieldName = t.nextToken();
1268 
1269                     // The field's Type must already be in the database -- no exceptions
1270                     Type fieldType = agent.getTypeDataBase().lookupType(t.nextToken());
1271 
1272                     boolean isStatic = Boolean.valueOf(t.nextToken()).booleanValue();
1273                     long offset = Long.parseLong(t.nextToken());
1274                     Address staticAddress = parseAddress(t.nextToken());
1275                     if (isStatic && staticAddress == null) {
1276                         staticAddress = lookup(containingType.getName() + "::" + fieldName);
1277                     }
1278 
1279                     // check to see if the field already exists
1280                     Iterator i = containingType.getFields();
1281                     while (i.hasNext()) {
1282                         Field f = (Field) i.next();
1283                         if (f.getName().equals(fieldName)) {
1284                             if (f.isStatic() != isStatic) {
1285                                 throw new RuntimeException("static/nonstatic mismatch: " + t.input);
1286                             }
1287                             if (!isStatic) {
1288                                 if (f.getOffset() != offset) {
1289                                     throw new RuntimeException("bad redefinition of field offset: " + t.input);
1290                                 }
1291                             } else {
1292                                 if (!f.getStaticFieldAddress().equals(staticAddress)) {
1293                                     throw new RuntimeException("bad redefinition of field location: " + t.input);
1294                                 }
1295                             }
1296                             if (f.getType() != fieldType) {
1297                                 throw new RuntimeException("bad redefinition of field type: " + t.input);
1298                             }
1299                             return;
1300                         }
1301                     }
1302 
1303                     // Create field by type
1304                     HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();
1305                     db.createField(containingType,
1306                                    fieldName, fieldType,
1307                                    isStatic,
1308                                    offset,
1309                                    staticAddress);
1310 
1311                 }
1312             }
1313 
1314         },
1315         new Command("tokenize", "tokenize ...", true) {
1316             public void doit(Tokens t) {

1317                 while (t.hasMoreTokens()) {
1318                     out.println("\"" + t.nextToken() + "\"");
1319                 }
1320             }
1321         },
1322         new Command("type", "type [ type [ name super isOop isInteger isUnsigned size ] ]", true) {
1323             public void doit(Tokens t) {

1324                 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) {
1325                     usage();
1326                     return;
1327                 }
1328                 if (t.countTokens() == 6) {
1329                     String typeName = t.nextToken();
1330                     String superclassName = t.nextToken();
1331                     if (superclassName.equals("null")) {
1332                         superclassName = null;
1333                     }
1334                     boolean isOop = Boolean.valueOf(t.nextToken()).booleanValue();
1335                     boolean isInteger = Boolean.valueOf(t.nextToken()).booleanValue();
1336                     boolean isUnsigned = Boolean.valueOf(t.nextToken()).booleanValue();
1337                     long size = Long.parseLong(t.nextToken());
1338 
1339                     BasicType type = null;
1340                     try {
1341                         type = (BasicType)agent.getTypeDataBase().lookupType(typeName);
1342                     } catch (RuntimeException e) {
1343                     }
1344                     if (type != null) {
1345                         if (type.isOopType() != isOop) {
1346                             throw new RuntimeException("oop mismatch in type definition: " + t.input);
1347                         }
1348                         if (type.isCIntegerType() != isInteger) {
1349                             throw new RuntimeException("integer type mismatch in type definition: " + t.input);
1350                         }
1351                         if (type.isCIntegerType() && (((CIntegerType)type).isUnsigned()) != isUnsigned) {
1352                             throw new RuntimeException("unsigned mismatch in type definition: " + t.input);
1353                         }
1354                         if (type.getSuperclass() == null) {
1355                             if (superclassName != null) {
1356                                 if (type.getSize() == -1) {
1357                                     type.setSuperclass(agent.getTypeDataBase().lookupType(superclassName));
1358                                 } else {
1359                                     throw new RuntimeException("unexpected superclass in type definition: " + t.input);
1360                                 }
1361                             }
1362                         } else {
1363                             if (superclassName == null) {
1364                                 throw new RuntimeException("missing superclass in type definition: " + t.input);
1365                             }
1366                             if (!type.getSuperclass().getName().equals(superclassName)) {
1367                                 throw new RuntimeException("incorrect superclass in type definition: " + t.input);
1368                             }
1369                         }
1370                         if (type.getSize() != size) {
1371                             if (type.getSize() == -1) {
1372                                 type.setSize(size);
1373                             }
1374                             throw new RuntimeException("size mismatch in type definition: " + t.input);
1375                         }
1376                         return;
1377                     }
1378 
1379                     // Create type
1380                     HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();
1381                     db.createType(typeName, superclassName, isOop, isInteger, isUnsigned, size);
1382                 } else if (t.countTokens() == 1) {
1383                     Type type = agent.getTypeDataBase().lookupType(t.nextToken());
1384                     dumpType(type);
1385                 } else {
1386                     Iterator i = agent.getTypeDataBase().getTypes();
1387                     // Make sure the types are emitted in an order than can be read back in
1388                     HashSet emitted = new HashSet();
1389                     Stack pending = new Stack();
1390                     while (i.hasNext()) {
1391                         Type n = (Type)i.next();
1392                         if (emitted.contains(n.getName())) {
1393                             continue;
1394                         }
1395 
1396                         while (n != null && !emitted.contains(n.getName())) {
1397                             pending.push(n);
1398                             n = n.getSuperclass();
1399                         }
1400                         while (!pending.empty()) {
1401                             n = (Type)pending.pop();
1402                             dumpType(n);
1403                             emitted.add(n.getName());
1404                         }
1405                     }
1406                 }
1407             }
1408 
1409         },
1410         new Command("source", "source filename", true) {
1411             public void doit(Tokens t) {

1412                 if (t.countTokens() != 1) {
1413                     usage();
1414                     return;
1415                 }
1416                 String file = t.nextToken();
1417                 BufferedReader savedInput = in;
1418                 try {
1419                     BufferedReader input = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
1420                     in = input;
1421                     run(false);
1422                 } catch (Exception e) {
1423                     out.println("Error: " + e);
1424                     if (verboseExceptions) {
1425                         e.printStackTrace(out);
1426                     }
1427                 } finally {
1428                     in = savedInput;
1429                 }
1430 
1431             }
1432         },
1433         new Command("search", "search [ heap | perm | rawheap | codecache | threads ] value", false) {
1434             public void doit(Tokens t) {

1435                 if (t.countTokens() != 2) {
1436                     usage();
1437                     return;
1438                 }
1439                 String type = t.nextToken();
1440                 final Address value = VM.getVM().getDebugger().parseAddress(t.nextToken());
1441                 final long stride = VM.getVM().getAddressSize();
1442                 if (type.equals("threads")) {
1443                     Threads threads = VM.getVM().getThreads();
1444                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
1445                         JavaThread thread = threads.getJavaThreadAt(i);
1446                         Address base = thread.getStackBase();
1447                         Address end = thread.getLastJavaSP();
1448                         if (end == null) continue;
1449                         if (end.lessThan(base)) {
1450                             Address tmp = base;
1451                             base = end;
1452                             end = tmp;
1453                         }
1454                         //out.println("Searching " + base + " " + end);


1519                                             } catch (Exception e) {
1520                                                 out.println("Exception printing blob at " + base);
1521                                                 e.printStackTrace();
1522                                             }
1523                                         }
1524                                         out.println("found at " + base + "\n");
1525                                     }
1526                                     base = base.addOffsetTo(stride);
1527                                 }
1528                             }
1529                             public void epilogue() {
1530                             }
1531 
1532 
1533                         };
1534                     VM.getVM().getCodeCache().iterate(v);
1535 
1536                 }
1537             }
1538         },
1539         new Command("dumpcodecache", "dumpcodecache", false) {
1540             public void doit(Tokens t) {

1541                 if (t.countTokens() != 0) {
1542                     usage();
1543                 } else {
1544                     final PrintStream fout = out;
1545                     final HTMLGenerator gen = new HTMLGenerator(false);
1546                     CodeCacheVisitor v = new CodeCacheVisitor() {
1547                             public void prologue(Address start, Address end) {
1548                             }
1549                             public void visit(CodeBlob blob) {
1550                                 fout.println(gen.genHTML(blob.contentBegin()));
1551                             }
1552                             public void epilogue() {
1553                             }
1554 
1555 
1556                         };
1557                     VM.getVM().getCodeCache().iterate(v);
1558                 }
1559             }
1560         },
1561         new Command("where", "where { -a | id }", false) {
1562             public void doit(Tokens t) {

1563                 if (t.countTokens() != 1) {
1564                     usage();
1565                 } else {
1566                     String name = t.nextToken();
1567                     Threads threads = VM.getVM().getThreads();
1568                     boolean all = name.equals("-a");
1569                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
1570                         JavaThread thread = threads.getJavaThreadAt(i);
1571                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
1572                         thread.printThreadIDOn(new PrintStream(bos));
1573                         if (all || bos.toString().equals(name)) {
1574                             out.println("Thread " + bos.toString() + " Address: " + thread.getAddress());
1575                             HTMLGenerator gen = new HTMLGenerator(false);
1576                             try {
1577                                 out.println(gen.genHTMLForJavaStackTrace(thread));
1578                             } catch (Exception e) {
1579                                 err.println("Error: " + e);
1580                                 if (verboseExceptions) {
1581                                     e.printStackTrace(err);
1582                                 }
1583                             }
1584                             if (!all) return;
1585                         }
1586                     }
1587                     if (!all) out.println("Couldn't find thread " + name);
1588                 }
1589             }
1590         },
1591         new Command("thread", "thread { -a | id }", false) {
1592             public void doit(Tokens t) {

1593                 if (t.countTokens() != 1) {
1594                     usage();
1595                 } else {
1596                     String name = t.nextToken();
1597                     Threads threads = VM.getVM().getThreads();
1598                     boolean all = name.equals("-a");
1599                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
1600                         JavaThread thread = threads.getJavaThreadAt(i);
1601                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
1602                         thread.printThreadIDOn(new PrintStream(bos));
1603                         if (all || bos.toString().equals(name)) {
1604                             out.println("Thread " + bos.toString() + " Address " + thread.getAddress());
1605                             thread.printInfoOn(out);
1606                             out.println(" ");
1607                             if (!all) return;
1608                         }
1609                     }
1610                     if (!all) {
1611                         out.println("Couldn't find thread " + name);
1612                     }
1613                 }
1614             }
1615         },
1616 
1617         new Command("threads", false) {
1618             public void doit(Tokens t) {
1619                 if (t.countTokens() != 0) {
1620                     usage();
1621                 } else {
1622                     Threads threads = VM.getVM().getThreads();
1623                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
1624                         JavaThread thread = threads.getJavaThreadAt(i);
1625                         thread.printThreadIDOn(out);
1626                         out.println(" " + thread.getThreadName());
1627                         thread.printInfoOn(out);
1628                         out.println("\n...");
1629                     }
1630                 }
1631             }
1632         },
1633 
1634         new Command("livenmethods", false) {
1635             public void doit(Tokens t) {

1636                 if (t.countTokens() != 0) {
1637                     usage();
1638                 } else {
1639                     ArrayList nmethods = new ArrayList();
1640                     Threads threads = VM.getVM().getThreads();
1641                     HTMLGenerator gen = new HTMLGenerator(false);
1642                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
1643                         JavaThread thread = threads.getJavaThreadAt(i);
1644                         try {
1645                             for (JavaVFrame vf = thread.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {
1646                                 if (vf instanceof CompiledVFrame) {
1647                                     NMethod c = ((CompiledVFrame)vf).getCode();
1648                                     if (!nmethods.contains(c)) {
1649                                         nmethods.add(c);
1650                                         out.println(gen.genHTML(c));
1651                                     }
1652                                 }
1653                             }
1654                         } catch (Exception e) {
1655                             e.printStackTrace();
1656                         }
1657                     }
1658                 }
1659             }
1660         },
1661         new Command("g1regiondetails", false) {
1662             public void doit(Tokens t) {

1663                 if (t.countTokens() != 0) {
1664                     usage();
1665                 } else {
1666                     CollectedHeap heap = VM.getVM().getUniverse().heap();
1667                     if (!(heap instanceof G1CollectedHeap)) {
1668                         out.println("This command is valid only for G1GC.");
1669                         return;
1670                     }
1671                     out.println("Region Details:");
1672                     ((G1CollectedHeap)heap).printRegionDetails(out);
1673                 }
1674             }
1675         },
1676         new Command("universe", false) {
1677             public void doit(Tokens t) {

1678                 if (t.countTokens() != 0) {
1679                     usage();
1680                 } else {
1681                     Universe u = VM.getVM().getUniverse();
1682                     out.println("Heap Parameters:");
1683                     u.heap().printOn(out);
1684                 }
1685             }
1686         },
1687         new Command("verbose", "verbose true | false", true) {
1688             public void doit(Tokens t) {

1689                 if (t.countTokens() != 1) {
1690                     usage();
1691                 } else {
1692                     verboseExceptions = Boolean.valueOf(t.nextToken()).booleanValue();
1693                 }
1694             }
1695         },
1696         new Command("assert", "assert true | false", true) {
1697             public void doit(Tokens t) {

1698                 if (t.countTokens() != 1) {
1699                     usage();
1700                 } else {
1701                     Assert.ASSERTS_ENABLED = Boolean.valueOf(t.nextToken()).booleanValue();
1702                 }
1703             }
1704         },










1705     };
1706 
1707     private boolean verboseExceptions = false;
1708     private ArrayList history = new ArrayList();
1709     private HashMap commands = new HashMap();
1710     private boolean doEcho = false;
1711 
1712     private Command findCommand(String key) {
1713         return (Command)commands.get(key);
1714     }
1715 
1716     public void printPrompt() {
1717         out.print("hsdb> ");
1718     }
1719 
1720     private DebuggerInterface debugger;
1721     private HotSpotAgent agent;
1722     private JSJavaScriptEngine jsengine;
1723     private BufferedReader in;
1724     private PrintStream out;


1763                      this.getClass().getMethod("registerCommand",
1764                                 new Class[] {
1765                                      String.class, String.class, String.class
1766                                 }));
1767             } catch (NoSuchMethodException exp) {
1768                   // should not happen, see below...!!
1769                   exp.printStackTrace();
1770             }
1771             jsengine.start();
1772         }
1773         catch (Exception ex) {
1774             System.out.println("Warning! JS Engine can't start, some commands will not be available.");
1775             if (verboseExceptions) {
1776                 ex.printStackTrace(out);
1777             }
1778         }
1779         */
1780     }
1781 
1782     public void registerCommand(String cmd, String usage, final String func) {
1783         commands.put(cmd, new Command(cmd, usage, false) {
1784                               public void doit(Tokens t) {

1785                                   final int len = t.countTokens();
1786                                   Object[] args = new Object[len];
1787                                   for (int i = 0; i < len; i++) {
1788                                       args[i] = t.nextToken();
1789                                   }
1790                                   jsengine.call(func, args);
1791                               }
1792                           });
1793     }
1794 































1795     public void setOutput(PrintStream o) {
1796         out = o;
1797     }
1798 
1799     public void setErr(PrintStream e) {
1800         err = e;
1801     }
1802 
1803     public CommandProcessor(DebuggerInterface debugger, BufferedReader in, PrintStream out, PrintStream err) {
1804         this.debugger = debugger;
1805         this.agent = debugger.getAgent();
1806         this.in = in;
1807         this.out = out;
1808         this.err = err;
1809         for (int i = 0; i < commandList.length; i++) {
1810             Command c = commandList[i];
1811             if (commands.get(c.name) != null) {
1812                 throw new InternalError(c.name + " has multiple definitions");
1813             }
1814             commands.put(c.name, c);
1815         }
1816         if (debugger.isAttached()) {
1817             postAttach();
1818         }
1819     }
1820 
1821 
1822     public void run(boolean prompt) {
1823         // Process interactive commands.
1824         while (!quit) {
1825             if (prompt) printPrompt();
1826             String ln = null;
1827             try {
1828                 ln = in.readLine();
1829             } catch (IOException e) {
1830             }
1831             if (ln == null) {
1832                 if (prompt) err.println("Input stream closed.");
1833                 return;
1834             }


1962                 } finally {
1963                     if (redirect != null) {
1964                         out = savedout;
1965                         redirect.close();
1966                     }
1967                 }
1968             }
1969         }
1970     }
1971 
1972     void executeCommand(Tokens args) {
1973         String cmd = args.nextToken();
1974 
1975         Command doit = findCommand(cmd);
1976 
1977         /*
1978          * Check for an unknown command
1979          */
1980         if (doit == null) {
1981             out.println("Unrecognized command.  Try help...");
1982         } else if (!debugger.isAttached() && !doit.okIfDisconnected) {
1983             out.println("Command not valid until attached to a VM");
1984         } else {
1985             try {
1986                 doit.doit(args);
1987             } catch (Exception e) {
1988                 out.println("Error: " + e);
1989                 if (verboseExceptions) {
1990                     e.printStackTrace(out);
1991                 }
1992             }
1993         }
1994     }
1995 }


   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;
  26 
  27 import java.lang.module.Configuration;
  28 import java.lang.module.ModuleFinder;
  29 import java.nio.file.Path;
  30 import java.io.BufferedOutputStream;
  31 import java.io.BufferedReader;
  32 import java.io.ByteArrayOutputStream;
  33 import java.io.FileInputStream;
  34 import java.io.FileOutputStream;
  35 import java.io.IOException;
  36 import java.io.InputStreamReader;
  37 import java.io.PrintStream;
  38 import java.util.ArrayList;
  39 import java.util.Arrays;
  40 import java.util.Collections;
  41 import java.util.Comparator;
  42 import java.util.HashMap;
  43 import java.util.HashSet;
  44 import java.util.Iterator;
  45 import java.util.ServiceLoader;
  46 import java.util.Set;
  47 import java.util.Stack;
  48 import java.util.stream.Collectors;
  49 import java.util.regex.Matcher;
  50 import java.util.regex.Pattern;
  51 
  52 import sun.jvm.hotspot.api.Command;
  53 import sun.jvm.hotspot.api.Tokens;
  54 import sun.jvm.hotspot.ci.ciEnv;
  55 import sun.jvm.hotspot.code.CodeBlob;
  56 import sun.jvm.hotspot.code.CodeCacheVisitor;
  57 import sun.jvm.hotspot.code.NMethod;
  58 import sun.jvm.hotspot.debugger.Address;
  59 import sun.jvm.hotspot.debugger.OopHandle;
  60 import sun.jvm.hotspot.classfile.ClassLoaderDataGraph;
  61 import sun.jvm.hotspot.memory.FileMapInfo;
  62 import sun.jvm.hotspot.memory.SystemDictionary;
  63 import sun.jvm.hotspot.memory.Universe;
  64 import sun.jvm.hotspot.gc.shared.CollectedHeap;
  65 import sun.jvm.hotspot.gc.g1.G1CollectedHeap;
  66 import sun.jvm.hotspot.oops.DefaultHeapVisitor;
  67 import sun.jvm.hotspot.oops.HeapVisitor;
  68 import sun.jvm.hotspot.oops.InstanceKlass;
  69 import sun.jvm.hotspot.oops.Klass;
  70 import sun.jvm.hotspot.oops.Metadata;
  71 import sun.jvm.hotspot.oops.Method;
  72 import sun.jvm.hotspot.oops.MethodData;
  73 import sun.jvm.hotspot.oops.Oop;


 130         public boolean canInclude(InstanceKlass kls) {
 131             return kls.getClassLoader() == null;
 132         }
 133     }
 134 
 135     public static class NonBootFilter implements ClassFilter {
 136         private HashMap emitted = new HashMap();
 137         public boolean canInclude(InstanceKlass kls) {
 138             if (kls.getClassLoader() == null) return false;
 139             if (emitted.get(kls.getName()) != null) {
 140                 // Since multiple class loaders are being shoved
 141                 // together duplicate classes are a possibilty.  For
 142                 // now just ignore them.
 143                 return false;
 144             }
 145             emitted.put(kls.getName(), kls);
 146             return true;
 147         }
 148     }
 149 
 150     abstract class ClhsdbCommand implements Command {
 151         ClhsdbCommand(String n, String u, boolean ok) {









































































































 152             name = n;
 153             usage = u;
 154             okIfDisconnected = ok;
 155         }
 156 
 157         ClhsdbCommand(String n, boolean ok) {
 158             name = n;
 159             usage = n;
 160             okIfDisconnected = ok;
 161         }
 162 
 163         private final String name;
 164         private final String usage;
 165         private final boolean okIfDisconnected;
 166 
 167         @Override
 168         public String name() {
 169             return name;
 170         }
 171 
 172         @Override
 173         public String usage() {
 174             return "Usage: " + usage;
 175         }
 176 
 177         @Override
 178         public boolean okIfDisconnected() {
 179             return okIfDisconnected;
 180         }
 181 
 182         @Override
 183         public abstract void doit(Tokens t, PrintStream out);
 184 
 185         void printOopValue(Oop oop) {
 186             if (oop != null) {
 187                 Klass k = oop.getKlass();
 188                 Symbol s = k.getName();
 189                 if (s != null) {
 190                     out.print("Oop for " + s.asString() + " @ ");
 191                 } else {
 192                     out.print("Oop @ ");
 193                 }
 194                 Oop.printOopAddressOn(oop, out);
 195             } else {
 196                 out.print("null");
 197             }
 198         }
 199 
 200         void printNode(SimpleTreeNode node) {
 201             int count = node.getChildCount();
 202             for (int i = 0; i < count; i++) {
 203                 try {
 204                     SimpleTreeNode field = node.getChild(i);


 291             for (int i = 0; i < parts.length; i++) {
 292                 int len = parts[i].length();
 293                 if (len >= 26) {
 294                     mangled.append((char)('a' + (len / 26)));
 295                     len = len % 26;
 296                 }
 297                 mangled.append((char)('A' + len));
 298                 mangled.append(parts[i]);
 299             }
 300             mangled.append("_");
 301             symbol = mangled.toString();
 302         }
 303         return VM.getVM().getDebugger().lookup(null, symbol);
 304     }
 305 
 306     Address parseAddress(String addr) {
 307         return VM.getVM().getDebugger().parseAddress(addr);
 308     }
 309 
 310     private final Command[] commandList = {
 311         new ClhsdbCommand("reattach", true) {
 312             @Override
 313             public void doit(Tokens t, PrintStream out) {
 314                 int tokens = t.countTokens();
 315                 if (tokens != 0) {
 316                     usage();
 317                     return;
 318                 }
 319                 preAttach();
 320                 debugger.reattach();
 321                 postAttach();
 322             }
 323         },
 324         new ClhsdbCommand("attach", "attach pid | exec core", true) {
 325             @Override
 326             public void doit(Tokens t, PrintStream out) {
 327                 int tokens = t.countTokens();
 328                 if (tokens == 1) {
 329                     preAttach();
 330                     debugger.attach(t.nextToken());
 331                     postAttach();
 332                 } else if (tokens == 2) {
 333                     preAttach();
 334                     debugger.attach(t.nextToken(), t.nextToken());
 335                     postAttach();
 336                 } else {
 337                     usage();
 338                 }
 339             }
 340         },
 341         new ClhsdbCommand("detach", false) {
 342             @Override
 343             public void doit(Tokens t, PrintStream out) {
 344                 if (t.countTokens() != 0) {
 345                     usage();
 346                 } else {
 347                     debugger.detach();
 348                 }
 349             }
 350         },
 351         new ClhsdbCommand("examine", "examine [ address/count ] | [ address,address]", false) {
 352             Pattern args1 = Pattern.compile("^(0x[0-9a-f]+)(/([0-9]*)([a-z]*))?$");
 353             Pattern args2 = Pattern.compile("^(0x[0-9a-f]+),(0x[0-9a-f]+)(/[a-z]*)?$");
 354 
 355             String fill(Address a, int width) {
 356                 String s = "0x0";
 357                 if (a != null) {
 358                     s = a.toString();
 359                 }
 360                 if (s.length() != width) {
 361                     return s.substring(0, 2) + "000000000000000000000".substring(0, width - s.length()) + s.substring(2);
 362                 }
 363                 return s;
 364             }
 365 
 366             @Override
 367             public void doit(Tokens t, PrintStream out) {
 368                 if (t.countTokens() != 1) {
 369                     usage();
 370                 } else {
 371                     String arg = t.nextToken();
 372                     Matcher m1 = args1.matcher(arg);
 373                     Matcher m2 = args2.matcher(arg);
 374                     Address start = null;
 375                     Address end   = null;
 376                     String format = "";
 377                     int formatSize = (int)VM.getVM().getAddressSize();
 378 
 379                     if (m1.matches()) {
 380                         start = VM.getVM().getDebugger().parseAddress(m1.group(1));
 381                         int count = 1;
 382                         if (m1.group(2) != null) {
 383                             count = Integer.parseInt(m1.group(3));
 384                         }
 385                         end = start.addOffsetTo(count * formatSize);
 386                     } else if (m2.matches()) {
 387                         start = VM.getVM().getDebugger().parseAddress(m2.group(1));


 406                         start = start.addOffsetTo(formatSize);
 407                         if (width <= formatWidth) {
 408                             out.println();
 409                             needsPrintln = false;
 410                             if (start.lessThan(end)) {
 411                                 out.print(fill(start, formatWidth));
 412                                 out.print(": ");
 413                                 width = line - formatWidth - 2;
 414                             }
 415                         } else {
 416                             out.print(" ");
 417                             width -= 1;
 418                         }
 419                     }
 420                     if (needsPrintln) {
 421                         out.println();
 422                     }
 423                 }
 424             }
 425         },
 426         new ClhsdbCommand("dumpreplaydata", "dumpreplaydata { <address > | -a | <thread_id> }", false) {
 427             // This is used to dump replay data from ciInstanceKlass, ciMethodData etc
 428             // default file name is replay.txt, also if java crashes in compiler
 429             // thread, this file will be dumped in error processing.
 430             @Override
 431             public void doit(Tokens t, PrintStream out) {
 432                 if (t.countTokens() != 1) {
 433                     usage();
 434                     return;
 435                 }
 436                 String name = t.nextToken();
 437                 Address a = null;
 438                 try {
 439                     a = VM.getVM().getDebugger().parseAddress(name);
 440                 } catch (NumberFormatException e) { }
 441                 if (a != null) {
 442                     // only nmethod, Method, MethodData and InstanceKlass needed to
 443                     // dump replay data
 444 
 445                     CodeBlob cb = VM.getVM().getCodeCache().findBlob(a);
 446                     if (cb != null && (cb instanceof NMethod)) {
 447                         ((NMethod)cb).dumpReplayData(out);
 448                         return;
 449                     }
 450                     // assume it is Metadata
 451                     Metadata meta = Metadata.instantiateWrapperFor(a);


 458                 }
 459                 // Not an address
 460                 boolean all = name.equals("-a");
 461                 Threads threads = VM.getVM().getThreads();
 462                 for (int i = 0; i < threads.getNumberOfThreads(); i++) {
 463                     JavaThread thread = threads.getJavaThreadAt(i);
 464                     ByteArrayOutputStream bos = new ByteArrayOutputStream();
 465                     thread.printThreadIDOn(new PrintStream(bos));
 466                     if (all || bos.toString().equals(name)) {
 467                         if (thread instanceof CompilerThread) {
 468                             CompilerThread ct = (CompilerThread)thread;
 469                             ciEnv env = ct.env();
 470                             if (env != null) {
 471                                env.dumpReplayData(out);
 472                             }
 473                         }
 474                     }
 475                 }
 476             }
 477         },
 478         new ClhsdbCommand("buildreplayjars", "buildreplayjars [ all | app | boot ]  | [ prefix ]", false) {
 479             // This is used to dump jar files of all the classes
 480             // loaded in the core.  Everything with null classloader
 481             // will go in boot.jar and everything else will go in
 482             // app.jar. boot.jar usually not needed, unless changed by jvmti.
 483             @Override
 484             public void doit(Tokens t, PrintStream out) {
 485                 int tcount = t.countTokens();
 486                 if (tcount > 2) {
 487                     usage();
 488                     return;
 489                 }
 490                 try {
 491                    String prefix = "";
 492                    String option = "all"; // default
 493                    switch(tcount) {
 494                        case 0:
 495                            break;
 496                        case 1:
 497                            option = t.nextToken();
 498                            if (!option.equalsIgnoreCase("all") && !option.equalsIgnoreCase("app") &&
 499                                !option.equalsIgnoreCase("root")) {
 500                               prefix = option;
 501                               option = "all";
 502                            }
 503                            break;
 504                        case 2:


 513                                !option.equalsIgnoreCase("boot")) {
 514                        usage();
 515                        return;
 516                    }
 517                    ClassDump cd = new ClassDump();
 518                    if (option.equalsIgnoreCase("all") || option.equalsIgnoreCase("boot")) {
 519                      cd.setClassFilter(new BootFilter());
 520                      cd.setJarOutput(prefix + "boot.jar");
 521                      cd.run();
 522                    }
 523                    if (option.equalsIgnoreCase("all") || option.equalsIgnoreCase("app")) {
 524                      cd.setClassFilter(new NonBootFilter());
 525                      cd.setJarOutput(prefix + "app.jar");
 526                      cd.run();
 527                    }
 528                 } catch (IOException ioe) {
 529                    ioe.printStackTrace();
 530                 }
 531             }
 532         },
 533         new ClhsdbCommand("findpc", "findpc address", false) {
 534             @Override
 535             public void doit(Tokens t, PrintStream out) {
 536                 if (t.countTokens() != 1) {
 537                     usage();
 538                 } else {
 539                     Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
 540                     PointerLocation loc = PointerFinder.find(a);
 541                     loc.printOn(out);
 542                 }
 543             }
 544         },
 545         new ClhsdbCommand("symbol", "symbol address", false) {
 546             @Override
 547             public void doit(Tokens t, PrintStream out) {
 548                 if (t.countTokens() != 1) {
 549                     usage();
 550                 } else {
 551                     Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
 552                     Symbol.create(a).printValueOn(out);
 553                     out.println();
 554                 }
 555             }
 556         },
 557         new ClhsdbCommand("flags", "flags [ flag | -nd ]", false) {
 558             @Override
 559             public void doit(Tokens t, PrintStream out) {
 560                 int tokens = t.countTokens();
 561                 if (tokens != 0 && tokens != 1) {
 562                     usage();
 563                 } else {
 564                     String name = tokens > 0 ? t.nextToken() : null;
 565                     boolean nonDefault = false;
 566                     if (name != null && name.equals("-nd")) {
 567                         name = null;
 568                         nonDefault = true;
 569                     }
 570 
 571                     VM.Flag[] flags = VM.getVM().getCommandLineFlags();
 572                     if (flags == null) {
 573                         out.println("Command Flag info not available (use 1.4.1_03 or later)!");
 574                     } else {
 575                         boolean printed = false;
 576                         for (int f = 0; f < flags.length; f++) {
 577                             VM.Flag flag = flags[f];
 578                             if (name == null || flag.getName().equals(name)) {
 579 
 580                                 if (nonDefault && (flag.getOrigin() == VM.Flags_DEFAULT)) {
 581                                     // only print flags which aren't their defaults
 582                                     continue;
 583                                 }
 584                                 out.println(flag.getName() + " = " + flag.getValue() + " " + flag.getOriginString());
 585                                 printed = true;
 586                             }
 587                         }
 588                         if (name != null && !printed) {
 589                             out.println("Couldn't find flag: " + name);
 590                         }
 591                     }
 592                 }
 593             }
 594         },
 595         new ClhsdbCommand("help", "help [ command ]", true) {
 596             @Override
 597             public void doit(Tokens t, PrintStream out) {
 598                 int tokens = t.countTokens();
 599                 Command cmd = null;
 600                 if (tokens == 1) {
 601                     cmd = findCommand(t.nextToken());
 602                 }
 603 
 604                 if (cmd != null) {
 605                     cmd.usage();
 606                 } else if (tokens == 0) {
 607                     out.println("Available commands:");
 608                     Object[] keys = commands.keySet().toArray();
 609                     Arrays.sort(keys, new Comparator() {
 610                              public int compare(Object o1, Object o2) {
 611                                  return o1.toString().compareTo(o2.toString());
 612                              }
 613                           });
 614                     for (int i = 0; i < keys.length; i++) {
 615                         out.print("  ");
 616                         out.println(((Command)commands.get(keys[i])).usage());
 617                     }
 618                 }
 619             }
 620         },
 621         new ClhsdbCommand("history", "history", true) {
 622             @Override
 623             public void doit(Tokens t, PrintStream out) {
 624                 int tokens = t.countTokens();
 625                 if (tokens != 0 && (tokens != 1 || !t.nextToken().equals("-h"))) {
 626                     usage();
 627                     return;
 628                 }
 629                 boolean printIndex = tokens == 0;
 630                 for (int i = 0; i < history.size(); i++) {
 631                     if (printIndex) out.print(i + " ");
 632                     out.println(history.get(i));
 633                 }
 634             }
 635         },
 636         // decode raw address
 637         new ClhsdbCommand("dis", "dis address [length]", false) {
 638             @Override
 639             public void doit(Tokens t, PrintStream out) {
 640                 int tokens = t.countTokens();
 641                 if (tokens != 1 && tokens != 2) {
 642                     usage();
 643                     return;
 644                 }
 645                 String name = t.nextToken();
 646                 Address addr = null;
 647                 int len = 0x10; // default length
 648                 try {
 649                     addr = VM.getVM().getDebugger().parseAddress(name);
 650                 } catch (NumberFormatException e) {
 651                    out.println(e);
 652                    return;
 653                 }
 654                 if (tokens == 2) {
 655                     try {
 656                         len = Integer.parseInt(t.nextToken());
 657                     } catch (NumberFormatException e) {
 658                         out.println(e);
 659                         return;
 660                     }
 661                 }
 662                 HTMLGenerator generator = new HTMLGenerator(false);
 663                 out.println(generator.genHTMLForRawDisassembly(addr, len));
 664             }
 665 
 666         },
 667         // decode codeblob or nmethod
 668         new ClhsdbCommand("disassemble", "disassemble address", false) {
 669             @Override
 670             public void doit(Tokens t, PrintStream out) {
 671                 int tokens = t.countTokens();
 672                 if (tokens != 1) {
 673                     usage();
 674                     return;
 675                 }
 676                 String name = t.nextToken();
 677                 Address addr = null;
 678                 try {
 679                     addr = VM.getVM().getDebugger().parseAddress(name);
 680                 } catch (NumberFormatException e) {
 681                    out.println(e);
 682                    return;
 683                 }
 684 
 685                 HTMLGenerator generator = new HTMLGenerator(false);
 686                 out.println(generator.genHTML(addr));
 687             }
 688         },
 689         // print Java bytecode disassembly
 690         new ClhsdbCommand("jdis", "jdis address", false) {
 691             @Override
 692             public void doit(Tokens t, PrintStream out) {
 693                 int tokens = t.countTokens();
 694                 if (tokens != 1) {
 695                     usage();
 696                     return;
 697                 }
 698                 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
 699                 Method m = (Method)Metadata.instantiateWrapperFor(a);
 700                 HTMLGenerator html = new HTMLGenerator(false);
 701                 out.println(html.genHTML(m));
 702             }
 703         },
 704         new ClhsdbCommand("revptrs", "revptrs address", false) {
 705             @Override
 706             public void doit(Tokens t, PrintStream out) {
 707                 int tokens = t.countTokens();
 708                 if (tokens != 1 && (tokens != 2 || !t.nextToken().equals("-c"))) {
 709                     usage();
 710                     return;
 711                 }
 712                 boolean chase = tokens == 2;
 713                 ReversePtrs revptrs = VM.getVM().getRevPtrs();
 714                 if (revptrs == null) {
 715                     out.println("Computing reverse pointers...");
 716                     ReversePtrsAnalysis analysis = new ReversePtrsAnalysis();
 717                     final boolean[] complete = new boolean[1];
 718                     HeapProgressThunk thunk = new HeapProgressThunk() {
 719                             public void heapIterationFractionUpdate(double d) {}
 720                             public synchronized void heapIterationComplete() {
 721                                 complete[0] = true;
 722                                 notify();
 723                             }
 724                         };
 725                     analysis.setHeapProgressThunk(thunk);
 726                     analysis.run();


 747                             while (ptrs.size() == 1) {
 748                                 LivenessPathElement e = (LivenessPathElement)ptrs.get(0);
 749                                 ByteArrayOutputStream bos = new ByteArrayOutputStream();
 750                                 Oop.printOopValueOn(e.getObj(), new PrintStream(bos));
 751                                 out.println(bos.toString());
 752                                 ptrs = revptrs.get(e.getObj());
 753                             }
 754                         } else {
 755                             for (int i = 0; i < ptrs.size(); i++) {
 756                                 LivenessPathElement e = (LivenessPathElement)ptrs.get(i);
 757                                 ByteArrayOutputStream bos = new ByteArrayOutputStream();
 758                                 Oop.printOopValueOn(e.getObj(), new PrintStream(bos));
 759                                 out.println(bos.toString());
 760                                 oop = e.getObj();
 761                             }
 762                         }
 763                     }
 764                 }
 765             }
 766         },
 767         new ClhsdbCommand("printmdo", "printmdo [ -a | expression ]", false) {
 768             // Print every MDO in the heap or the one referenced by expression.
 769             @Override
 770             public void doit(Tokens t, PrintStream out) {
 771                 if (t.countTokens() != 1) {
 772                     usage();
 773                 } else {
 774                     String s = t.nextToken();
 775                     if (s.equals("-a")) {
 776                         ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
 777                         cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
 778                                 public void visit(Klass k) {
 779                                     if (k instanceof InstanceKlass) {
 780                                         MethodArray methods = ((InstanceKlass)k).getMethods();
 781                                         for (int i = 0; i < methods.length(); i++) {
 782                                             Method m = methods.at(i);
 783                                             MethodData mdo = m.getMethodData();
 784                                             if (mdo != null) {
 785                                                 out.println("MethodData " + mdo.getAddress() + " for " +
 786                                                     "method " + m.getMethodHolder().getName().asString() + "." +
 787                                                     m.getName().asString() +
 788                                                             m.getSignature().asString() + "@" + m.getAddress());
 789                                                 mdo.printDataOn(out);
 790                                     }
 791                                 }
 792                                     }
 793                                 }
 794                             }
 795                             );
 796                     } else {
 797                         Address a = VM.getVM().getDebugger().parseAddress(s);
 798                         MethodData mdo = (MethodData) Metadata.instantiateWrapperFor(a);
 799                         mdo.printDataOn(out);
 800                     }
 801                 }
 802             }
 803         },
 804         new ClhsdbCommand("printall", "printall", false) {
 805             // Print every MDO in the heap or the one referenced by expression.
 806             @Override
 807             public void doit(Tokens t, PrintStream out) {
 808                 if (t.countTokens() != 0) {
 809                     usage();
 810                 } else {
 811                     ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
 812                     cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
 813                             public void visit(Klass k) {
 814                                 if (k instanceof InstanceKlass && ((InstanceKlass)k).getConstants().getCache() != null) {
 815                                     MethodArray methods = ((InstanceKlass)k).getMethods();
 816                                     for (int i = 0; i < methods.length(); i++) {
 817                                         Method m = methods.at(i);
 818                                         HTMLGenerator gen = new HTMLGenerator(false);
 819                                         out.println(gen.genHTML(m));
 820                                     }
 821                                 }
 822                             }
 823                         }
 824                         );
 825                 }
 826             }
 827         },
 828         new ClhsdbCommand("dumpideal", "dumpideal { -a | id }", false) {
 829             // Do a full dump of the nodes reachabile from root in each compiler thread.
 830             @Override
 831             public void doit(Tokens t, PrintStream out) {
 832                 if (t.countTokens() != 1) {
 833                     usage();
 834                 } else {
 835                     String name = t.nextToken();
 836                     boolean all = name.equals("-a");
 837                     Threads threads = VM.getVM().getThreads();
 838                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
 839                         JavaThread thread = threads.getJavaThreadAt(i);
 840                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
 841                         thread.printThreadIDOn(new PrintStream(bos));
 842                         if (all || bos.toString().equals(name)) {
 843                           if (thread instanceof CompilerThread) {
 844                             CompilerThread ct = (CompilerThread)thread;
 845                             out.println(ct);
 846                             ciEnv env = ct.env();
 847                             if (env != null) {
 848                               Compile c = env.compilerData();
 849                               c.root().dump(9999, out);
 850                             } else {
 851                               out.println("  not compiling");
 852                             }
 853                           }
 854                         }
 855                     }
 856                 }
 857             }
 858         },
 859         new ClhsdbCommand("dumpcfg", "dumpcfg { -a | id }", false) {
 860             // Dump the PhaseCFG for every compiler thread that has one live.
 861             @Override
 862             public void doit(Tokens t, PrintStream out) {
 863                 if (t.countTokens() != 1) {
 864                     usage();
 865                 } else {
 866                     String name = t.nextToken();
 867                     boolean all = name.equals("-a");
 868                     Threads threads = VM.getVM().getThreads();
 869                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
 870                         JavaThread thread = threads.getJavaThreadAt(i);
 871                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
 872                         thread.printThreadIDOn(new PrintStream(bos));
 873                         if (all || bos.toString().equals(name)) {
 874                           if (thread instanceof CompilerThread) {
 875                             CompilerThread ct = (CompilerThread)thread;
 876                             out.println(ct);
 877                             ciEnv env = ct.env();
 878                             if (env != null) {
 879                               Compile c = env.compilerData();
 880                               c.cfg().dump(out);
 881                             }
 882                           }
 883                         }
 884                     }
 885                 }
 886             }
 887         },
 888         new ClhsdbCommand("dumpilt", "dumpilt { -a | id }", false) {
 889             // dumps the InlineTree of a C2 compile
 890             @Override
 891             public void doit(Tokens t, PrintStream out) {
 892                 if (t.countTokens() != 1) {
 893                     usage();
 894                 } else {
 895                     String name = t.nextToken();
 896                     boolean all = name.equals("-a");
 897                     Threads threads = VM.getVM().getThreads();
 898                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
 899                         JavaThread thread = threads.getJavaThreadAt(i);
 900                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
 901                         thread.printThreadIDOn(new PrintStream(bos));
 902                         if (all || bos.toString().equals(name)) {
 903                             if (thread instanceof CompilerThread) {
 904                                 CompilerThread ct = (CompilerThread)thread;
 905                                 ciEnv env = ct.env();
 906                                 if (env != null) {
 907                                     Compile c = env.compilerData();
 908                                     InlineTree ilt = c.ilt();
 909                                     if (ilt != null) {
 910                                         ilt.print(out);
 911                                     }
 912                                 }
 913                             }
 914                         }
 915                     }
 916                 }
 917             }
 918         },
 919         new ClhsdbCommand("vmstructsdump", "vmstructsdump", false) {
 920             @Override
 921             public void doit(Tokens t, PrintStream out) {
 922                 if (t.countTokens() != 0) {
 923                     usage();
 924                     return;
 925                 }
 926 
 927                 // Dump a copy of the type database in a form that can
 928                 // be read back.
 929                 Iterator i = agent.getTypeDataBase().getTypes();
 930                 // Make sure the types are emitted in an order than can be read back in
 931                 HashSet emitted = new HashSet();
 932                 Stack pending = new Stack();
 933                 while (i.hasNext()) {
 934                     Type n = (Type)i.next();
 935                     if (emitted.contains(n.getName())) {
 936                         continue;
 937                     }
 938 
 939                     while (n != null && !emitted.contains(n.getName())) {
 940                         pending.push(n);
 941                         n = n.getSuperclass();
 942                     }
 943                     while (!pending.empty()) {
 944                         n = (Type)pending.pop();
 945                         dumpType(n);
 946                         emitted.add(n.getName());
 947                     }
 948                 }
 949                 i = agent.getTypeDataBase().getTypes();
 950                 while (i.hasNext()) {
 951                     dumpFields((Type)i.next(), false);
 952                 }
 953             }
 954         },
 955 
 956         new ClhsdbCommand("inspect", "inspect expression", false) {
 957             @Override
 958             public void doit(Tokens t, PrintStream out) {
 959                 if (t.countTokens() != 1) {
 960                     usage();
 961                 } else {
 962                     Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
 963                     SimpleTreeNode node = null;
 964                     if (VM.getVM().getUniverse().heap().isInReserved(a)) {
 965                         OopHandle handle = a.addOffsetToAsOopHandle(0);
 966                         Oop oop = VM.getVM().getObjectHeap().newOop(handle);
 967                         node = new OopTreeNodeAdapter(oop, null);
 968 
 969                         out.println("instance of " + node.getValue() + " @ " + a +
 970                                     " (size = " + oop.getObjectSize() + ")");
 971                     } else if (VM.getVM().getCodeCache().contains(a)) {
 972                         CodeBlob blob = VM.getVM().getCodeCache().findBlobUnsafe(a);
 973                         a = blob.headerBegin();
 974                     }
 975                     if (node == null) {
 976                         Type type = VM.getVM().getTypeDataBase().guessTypeForAddress(a);
 977                         if (type == null && VM.getVM().isSharingEnabled()) {
 978                             // Check if the value falls in the _md_region
 979                             Address loc1 = a.getAddressAt(0);
 980                             FileMapInfo cdsFileMapInfo = VM.getVM().getFileMapInfo();
 981                             if (cdsFileMapInfo.inCopiedVtableSpace(loc1)) {
 982                                type = cdsFileMapInfo.getTypeForVptrAddress(loc1);
 983                             }
 984 
 985                         }
 986                         if (type != null) {
 987                             out.println("Type is " + type.getName() + " (size of " + type.getSize() + ")");
 988                             node = new CTypeTreeNodeAdapter(a, type, null);
 989                         }
 990                     }
 991                     if (node != null) {
 992                         printNode(node);
 993                     }
 994                 }
 995             }
 996         },
 997         new ClhsdbCommand("jhisto", "jhisto", false) {
 998             @Override
 999             public void doit(Tokens t, PrintStream out) {
1000                  ObjectHistogram histo = new ObjectHistogram();
1001                  histo.run(out, err);
1002             }
1003         },
1004         new ClhsdbCommand("jstack", "jstack [-v]", false) {
1005             @Override
1006             public void doit(Tokens t, PrintStream out) {
1007                 boolean verbose = false;
1008                 if (t.countTokens() > 0 && t.nextToken().equals("-v")) {
1009                     verbose = true;
1010                 }
1011                 StackTrace jstack = new StackTrace(verbose, true);
1012                 jstack.run(out);
1013             }
1014         },
1015         new ClhsdbCommand("print", "print expression", false) {
1016             @Override
1017             public void doit(Tokens t, PrintStream out) {
1018                 if (t.countTokens() != 1) {
1019                     usage();
1020                 } else {
1021                     Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
1022                     HTMLGenerator gen = new HTMLGenerator(false);
1023                     out.println(gen.genHTML(a));
1024                 }
1025             }
1026         },
1027         new ClhsdbCommand("printas", "printas type expression", false) {
1028             @Override
1029             public void doit(Tokens t, PrintStream out) {
1030                 if (t.countTokens() != 2) {
1031                     usage();
1032                 } else {
1033                     Type type = agent.getTypeDataBase().lookupType(t.nextToken());
1034                     Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
1035                     CTypeTreeNodeAdapter node = new CTypeTreeNodeAdapter(a, type, null);
1036 
1037                     out.println("pointer to " + type + " @ " + a +
1038                                 " (size = " + type.getSize() + ")");
1039                     printNode(node);
1040                 }
1041             }
1042         },
1043         new ClhsdbCommand("printstatics", "printstatics [ type ]", false) {
1044             @Override
1045             public void doit(Tokens t, PrintStream out) {
1046                 if (t.countTokens() > 1) {
1047                     usage();
1048                 } else {
1049                     if (t.countTokens() == 0) {
1050                         out.println("All known static fields");
1051                         printNode(new CTypeTreeNodeAdapter(agent.getTypeDataBase().getTypes()));
1052                     } else {
1053                         Type type = agent.getTypeDataBase().lookupType(t.nextToken());
1054                         out.println("Static fields of " + type.getName());
1055                         printNode(new CTypeTreeNodeAdapter(type));
1056                     }
1057                 }
1058             }
1059         },
1060         new ClhsdbCommand("pmap", "pmap", false) {
1061             @Override
1062             public void doit(Tokens t, PrintStream out) {
1063                 PMap pmap = new PMap();
1064                 pmap.run(out, debugger.getAgent().getDebugger());
1065             }
1066         },
1067         new ClhsdbCommand("pstack", "pstack [-v]", false) {
1068             @Override
1069             public void doit(Tokens t, PrintStream out) {
1070                 boolean verbose = false;
1071                 if (t.countTokens() > 0 && t.nextToken().equals("-v")) {
1072                     verbose = true;
1073                 }
1074                 PStack pstack = new PStack(verbose, true);
1075                 pstack.run(out, debugger.getAgent().getDebugger());
1076             }
1077         },
1078         new ClhsdbCommand("quit", true) {
1079             @Override
1080             public void doit(Tokens t, PrintStream out) {
1081                 if (t.countTokens() != 0) {
1082                     usage();
1083                 } else {
1084                     debugger.detach();
1085                     quit = true;
1086                 }
1087             }
1088         },
1089         new ClhsdbCommand("echo", "echo [ true | false ]", true) {
1090             @Override
1091             public void doit(Tokens t, PrintStream out) {
1092                 if (t.countTokens() == 0) {
1093                     out.println("echo is " + doEcho);
1094                 } else if (t.countTokens() == 1) {
1095                     doEcho = Boolean.valueOf(t.nextToken()).booleanValue();
1096                 } else {
1097                     usage();
1098                 }
1099             }
1100         },
1101         new ClhsdbCommand("versioncheck", "versioncheck [ true | false ]", true) {
1102             @Override
1103             public void doit(Tokens t, PrintStream out) {
1104                 if (t.countTokens() == 0) {
1105                     out.println("versioncheck is " +
1106                                 (System.getProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck") == null));
1107                 } else if (t.countTokens() == 1) {
1108                     if (Boolean.valueOf(t.nextToken()).booleanValue()) {
1109                         System.setProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck", null);
1110                     } else {
1111                         System.setProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck", "true");
1112                     }
1113                 } else {
1114                     usage();
1115                 }
1116             }
1117         },
1118         new ClhsdbCommand("scanoops", "scanoops start end [ type ]", false) {
1119             @Override
1120             public void doit(Tokens t, PrintStream out) {
1121                 if (t.countTokens() != 2 && t.countTokens() != 3) {
1122                     usage();
1123                 } else {
1124                     long stride = VM.getVM().getAddressSize();
1125                     Address base = VM.getVM().getDebugger().parseAddress(t.nextToken());
1126                     Address end  = VM.getVM().getDebugger().parseAddress(t.nextToken());
1127                     Klass klass = null;
1128                     if (t.countTokens() == 1) {
1129                         klass = SystemDictionaryHelper.findInstanceKlass(t.nextToken());
1130                         if (klass == null) {
1131                             out.println("No such type.");
1132                             return;
1133                         }
1134                     }
1135                     while (base != null && base.lessThan(end)) {
1136                         long step = stride;
1137                         OopHandle handle = base.addOffsetToAsOopHandle(0);
1138                         if (RobustOopDeterminator.oopLooksValid(handle)) {
1139                             try {
1140                                 Oop oop = VM.getVM().getObjectHeap().newOop(handle);
1141                                 if (klass == null || oop.getKlass().isSubtypeOf(klass))
1142                                     out.println(handle.toString() + " " + oop.getKlass().getName().asString());
1143                                 step = oop.getObjectSize();
1144                             } catch (UnknownOopException ex) {
1145                                 // ok
1146                             } catch (RuntimeException ex) {
1147                                 ex.printStackTrace();
1148                             }
1149                         }
1150                         base = base.addOffsetTo(step);
1151                     }
1152                 }
1153             }
1154         },
1155         new ClhsdbCommand("intConstant", "intConstant [ name [ value ] ]", true) {
1156             @Override
1157             public void doit(Tokens t, PrintStream out) {
1158                 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 2) {
1159                     usage();
1160                     return;
1161                 }
1162                 HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();
1163                 if (t.countTokens() == 1) {
1164                     String name = t.nextToken();
1165                     out.println("intConstant " + name + " " + db.lookupIntConstant(name));
1166                 } else if (t.countTokens() == 0) {
1167                     Iterator i = db.getIntConstants();
1168                     while (i.hasNext()) {
1169                         String name = (String)i.next();
1170                         out.println("intConstant " + name + " " + db.lookupIntConstant(name));
1171                     }
1172                 } else if (t.countTokens() == 2) {
1173                     String name = t.nextToken();
1174                     Integer value = Integer.valueOf(t.nextToken());
1175                     db.addIntConstant(name, value);
1176                 }
1177             }
1178         },
1179         new ClhsdbCommand("longConstant", "longConstant [ name [ value ] ]", true) {
1180             @Override
1181             public void doit(Tokens t, PrintStream out) {
1182                 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 2) {
1183                     usage();
1184                     return;
1185                 }
1186                 HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();
1187                 if (t.countTokens() == 1) {
1188                     String name = t.nextToken();
1189                     out.println("longConstant " + name + " " + db.lookupLongConstant(name));
1190                 } else if (t.countTokens() == 0) {
1191                     Iterator i = db.getLongConstants();
1192                     while (i.hasNext()) {
1193                         String name = (String)i.next();
1194                         out.println("longConstant " + name + " " + db.lookupLongConstant(name));
1195                     }
1196                 } else if (t.countTokens() == 2) {
1197                     String name = t.nextToken();
1198                     Long value = Long.valueOf(t.nextToken());
1199                     db.addLongConstant(name, value);
1200                 }
1201             }
1202         },
1203         new ClhsdbCommand("field", "field [ type [ name fieldtype isStatic offset address ] ]", true) {
1204             @Override
1205             public void doit(Tokens t, PrintStream out) {
1206                 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) {
1207                     usage();
1208                     return;
1209                 }
1210                 if (t.countTokens() == 1) {
1211                     Type type = agent.getTypeDataBase().lookupType(t.nextToken());
1212                     dumpFields(type);
1213                 } else if (t.countTokens() == 0) {
1214                     Iterator i = agent.getTypeDataBase().getTypes();
1215                     while (i.hasNext()) {
1216                         dumpFields((Type)i.next());
1217                     }
1218                 } else {
1219                     BasicType containingType = (BasicType)agent.getTypeDataBase().lookupType(t.nextToken());
1220 
1221                     String fieldName = t.nextToken();
1222 
1223                     // The field's Type must already be in the database -- no exceptions
1224                     Type fieldType = agent.getTypeDataBase().lookupType(t.nextToken());
1225 
1226                     boolean isStatic = Boolean.valueOf(t.nextToken()).booleanValue();
1227                     long offset = Long.parseLong(t.nextToken());
1228                     Address staticAddress = parseAddress(t.nextToken());
1229                     if (isStatic && staticAddress == null) {
1230                         staticAddress = lookup(containingType.getName() + "::" + fieldName);
1231                     }
1232 
1233                     // check to see if the field already exists
1234                     Iterator i = containingType.getFields();
1235                     while (i.hasNext()) {
1236                         Field f = (Field) i.next();
1237                         if (f.getName().equals(fieldName)) {
1238                             if (f.isStatic() != isStatic) {
1239                                 throw new RuntimeException("static/nonstatic mismatch: " + t.getInput());
1240                             }
1241                             if (!isStatic) {
1242                                 if (f.getOffset() != offset) {
1243                                     throw new RuntimeException("bad redefinition of field offset: " + t.getInput());
1244                                 }
1245                             } else {
1246                                 if (!f.getStaticFieldAddress().equals(staticAddress)) {
1247                                     throw new RuntimeException("bad redefinition of field location: " + t.getInput());
1248                                 }
1249                             }
1250                             if (f.getType() != fieldType) {
1251                                 throw new RuntimeException("bad redefinition of field type: " + t.getInput());
1252                             }
1253                             return;
1254                         }
1255                     }
1256 
1257                     // Create field by type
1258                     HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();
1259                     db.createField(containingType,
1260                                    fieldName, fieldType,
1261                                    isStatic,
1262                                    offset,
1263                                    staticAddress);
1264 
1265                 }
1266             }
1267 
1268         },
1269         new ClhsdbCommand("tokenize", "tokenize ...", true) {
1270             @Override
1271             public void doit(Tokens t, PrintStream out) {
1272                 while (t.hasMoreTokens()) {
1273                     out.println("\"" + t.nextToken() + "\"");
1274                 }
1275             }
1276         },
1277         new ClhsdbCommand("type", "type [ type [ name super isOop isInteger isUnsigned size ] ]", true) {
1278             @Override
1279             public void doit(Tokens t, PrintStream out) {
1280                 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) {
1281                     usage();
1282                     return;
1283                 }
1284                 if (t.countTokens() == 6) {
1285                     String typeName = t.nextToken();
1286                     String superclassName = t.nextToken();
1287                     if (superclassName.equals("null")) {
1288                         superclassName = null;
1289                     }
1290                     boolean isOop = Boolean.valueOf(t.nextToken()).booleanValue();
1291                     boolean isInteger = Boolean.valueOf(t.nextToken()).booleanValue();
1292                     boolean isUnsigned = Boolean.valueOf(t.nextToken()).booleanValue();
1293                     long size = Long.parseLong(t.nextToken());
1294 
1295                     BasicType type = null;
1296                     try {
1297                         type = (BasicType)agent.getTypeDataBase().lookupType(typeName);
1298                     } catch (RuntimeException e) {
1299                     }
1300                     if (type != null) {
1301                         if (type.isOopType() != isOop) {
1302                             throw new RuntimeException("oop mismatch in type definition: " + t.getInput());
1303                         }
1304                         if (type.isCIntegerType() != isInteger) {
1305                             throw new RuntimeException("integer type mismatch in type definition: " + t.getInput());
1306                         }
1307                         if (type.isCIntegerType() && (((CIntegerType)type).isUnsigned()) != isUnsigned) {
1308                             throw new RuntimeException("unsigned mismatch in type definition: " + t.getInput());
1309                         }
1310                         if (type.getSuperclass() == null) {
1311                             if (superclassName != null) {
1312                                 if (type.getSize() == -1) {
1313                                     type.setSuperclass(agent.getTypeDataBase().lookupType(superclassName));
1314                                 } else {
1315                                     throw new RuntimeException("unexpected superclass in type definition: " + t.getInput());
1316                                 }
1317                             }
1318                         } else {
1319                             if (superclassName == null) {
1320                                 throw new RuntimeException("missing superclass in type definition: " + t.getInput());
1321                             }
1322                             if (!type.getSuperclass().getName().equals(superclassName)) {
1323                                 throw new RuntimeException("incorrect superclass in type definition: " + t.getInput());
1324                             }
1325                         }
1326                         if (type.getSize() != size) {
1327                             if (type.getSize() == -1) {
1328                                 type.setSize(size);
1329                             }
1330                             throw new RuntimeException("size mismatch in type definition: " + t.getInput());
1331                         }
1332                         return;
1333                     }
1334 
1335                     // Create type
1336                     HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();
1337                     db.createType(typeName, superclassName, isOop, isInteger, isUnsigned, size);
1338                 } else if (t.countTokens() == 1) {
1339                     Type type = agent.getTypeDataBase().lookupType(t.nextToken());
1340                     dumpType(type);
1341                 } else {
1342                     Iterator i = agent.getTypeDataBase().getTypes();
1343                     // Make sure the types are emitted in an order than can be read back in
1344                     HashSet emitted = new HashSet();
1345                     Stack pending = new Stack();
1346                     while (i.hasNext()) {
1347                         Type n = (Type)i.next();
1348                         if (emitted.contains(n.getName())) {
1349                             continue;
1350                         }
1351 
1352                         while (n != null && !emitted.contains(n.getName())) {
1353                             pending.push(n);
1354                             n = n.getSuperclass();
1355                         }
1356                         while (!pending.empty()) {
1357                             n = (Type)pending.pop();
1358                             dumpType(n);
1359                             emitted.add(n.getName());
1360                         }
1361                     }
1362                 }
1363             }
1364 
1365         },
1366         new ClhsdbCommand("source", "source filename", true) {
1367             @Override
1368             public void doit(Tokens t, PrintStream out) {
1369                 if (t.countTokens() != 1) {
1370                     usage();
1371                     return;
1372                 }
1373                 String file = t.nextToken();
1374                 BufferedReader savedInput = in;
1375                 try {
1376                     BufferedReader input = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
1377                     in = input;
1378                     run(false);
1379                 } catch (Exception e) {
1380                     out.println("Error: " + e);
1381                     if (verboseExceptions) {
1382                         e.printStackTrace(out);
1383                     }
1384                 } finally {
1385                     in = savedInput;
1386                 }
1387 
1388             }
1389         },
1390         new ClhsdbCommand("search", "search [ heap | perm | rawheap | codecache | threads ] value", false) {
1391             @Override
1392             public void doit(Tokens t, PrintStream out) {
1393                 if (t.countTokens() != 2) {
1394                     usage();
1395                     return;
1396                 }
1397                 String type = t.nextToken();
1398                 final Address value = VM.getVM().getDebugger().parseAddress(t.nextToken());
1399                 final long stride = VM.getVM().getAddressSize();
1400                 if (type.equals("threads")) {
1401                     Threads threads = VM.getVM().getThreads();
1402                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
1403                         JavaThread thread = threads.getJavaThreadAt(i);
1404                         Address base = thread.getStackBase();
1405                         Address end = thread.getLastJavaSP();
1406                         if (end == null) continue;
1407                         if (end.lessThan(base)) {
1408                             Address tmp = base;
1409                             base = end;
1410                             end = tmp;
1411                         }
1412                         //out.println("Searching " + base + " " + end);


1477                                             } catch (Exception e) {
1478                                                 out.println("Exception printing blob at " + base);
1479                                                 e.printStackTrace();
1480                                             }
1481                                         }
1482                                         out.println("found at " + base + "\n");
1483                                     }
1484                                     base = base.addOffsetTo(stride);
1485                                 }
1486                             }
1487                             public void epilogue() {
1488                             }
1489 
1490 
1491                         };
1492                     VM.getVM().getCodeCache().iterate(v);
1493 
1494                 }
1495             }
1496         },
1497         new ClhsdbCommand("dumpcodecache", "dumpcodecache", false) {
1498             @Override
1499             public void doit(Tokens t, PrintStream out) {
1500                 if (t.countTokens() != 0) {
1501                     usage();
1502                 } else {
1503                     final PrintStream fout = out;
1504                     final HTMLGenerator gen = new HTMLGenerator(false);
1505                     CodeCacheVisitor v = new CodeCacheVisitor() {
1506                             public void prologue(Address start, Address end) {
1507                             }
1508                             public void visit(CodeBlob blob) {
1509                                 fout.println(gen.genHTML(blob.contentBegin()));
1510                             }
1511                             public void epilogue() {
1512                             }
1513 
1514 
1515                         };
1516                     VM.getVM().getCodeCache().iterate(v);
1517                 }
1518             }
1519         },
1520         new ClhsdbCommand("where", "where { -a | id }", false) {
1521             @Override
1522             public void doit(Tokens t, PrintStream out) {
1523                 if (t.countTokens() != 1) {
1524                     usage();
1525                 } else {
1526                     String name = t.nextToken();
1527                     Threads threads = VM.getVM().getThreads();
1528                     boolean all = name.equals("-a");
1529                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
1530                         JavaThread thread = threads.getJavaThreadAt(i);
1531                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
1532                         thread.printThreadIDOn(new PrintStream(bos));
1533                         if (all || bos.toString().equals(name)) {
1534                             out.println("Thread " + bos.toString() + " Address: " + thread.getAddress());
1535                             HTMLGenerator gen = new HTMLGenerator(false);
1536                             try {
1537                                 out.println(gen.genHTMLForJavaStackTrace(thread));
1538                             } catch (Exception e) {
1539                                 err.println("Error: " + e);
1540                                 if (verboseExceptions) {
1541                                     e.printStackTrace(err);
1542                                 }
1543                             }
1544                             if (!all) return;
1545                         }
1546                     }
1547                     if (!all) out.println("Couldn't find thread " + name);
1548                 }
1549             }
1550         },
1551         new ClhsdbCommand("thread", "thread { -a | id }", false) {
1552             @Override
1553             public void doit(Tokens t, PrintStream out) {
1554                 if (t.countTokens() != 1) {
1555                     usage();
1556                 } else {
1557                     String name = t.nextToken();
1558                     Threads threads = VM.getVM().getThreads();
1559                     boolean all = name.equals("-a");
1560                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
1561                         JavaThread thread = threads.getJavaThreadAt(i);
1562                         ByteArrayOutputStream bos = new ByteArrayOutputStream();
1563                         thread.printThreadIDOn(new PrintStream(bos));
1564                         if (all || bos.toString().equals(name)) {
1565                             out.println("Thread " + bos.toString() + " Address " + thread.getAddress());
1566                             thread.printInfoOn(out);
1567                             out.println(" ");
1568                             if (!all) return;
1569                         }
1570                     }
1571                     if (!all) {
1572                         out.println("Couldn't find thread " + name);
1573                     }
1574                 }
1575             }
1576         },
1577 
1578         new ClhsdbCommand("threads", false) {
1579             public void doit(Tokens t, PrintStream out) {
1580                 if (t.countTokens() != 0) {
1581                     usage();
1582                 } else {
1583                     Threads threads = VM.getVM().getThreads();
1584                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
1585                         JavaThread thread = threads.getJavaThreadAt(i);
1586                         thread.printThreadIDOn(out);
1587                         out.println(" " + thread.getThreadName());
1588                         thread.printInfoOn(out);
1589                         out.println("\n...");
1590                     }
1591                 }
1592             }
1593         },
1594 
1595         new ClhsdbCommand("livenmethods", false) {
1596             @Override
1597             public void doit(Tokens t, PrintStream out) {
1598                 if (t.countTokens() != 0) {
1599                     usage();
1600                 } else {
1601                     ArrayList nmethods = new ArrayList();
1602                     Threads threads = VM.getVM().getThreads();
1603                     HTMLGenerator gen = new HTMLGenerator(false);
1604                     for (int i = 0; i < threads.getNumberOfThreads(); i++) {
1605                         JavaThread thread = threads.getJavaThreadAt(i);
1606                         try {
1607                             for (JavaVFrame vf = thread.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {
1608                                 if (vf instanceof CompiledVFrame) {
1609                                     NMethod c = ((CompiledVFrame)vf).getCode();
1610                                     if (!nmethods.contains(c)) {
1611                                         nmethods.add(c);
1612                                         out.println(gen.genHTML(c));
1613                                     }
1614                                 }
1615                             }
1616                         } catch (Exception e) {
1617                             e.printStackTrace();
1618                         }
1619                     }
1620                 }
1621             }
1622         },
1623         new ClhsdbCommand("g1regiondetails", false) {
1624             @Override
1625             public void doit(Tokens t, PrintStream out) {
1626                 if (t.countTokens() != 0) {
1627                     usage();
1628                 } else {
1629                     CollectedHeap heap = VM.getVM().getUniverse().heap();
1630                     if (!(heap instanceof G1CollectedHeap)) {
1631                         out.println("This command is valid only for G1GC.");
1632                         return;
1633                     }
1634                     out.println("Region Details:");
1635                     ((G1CollectedHeap)heap).printRegionDetails(out);
1636                 }
1637             }
1638         },
1639         new ClhsdbCommand("universe", false) {
1640             @Override
1641             public void doit(Tokens t, PrintStream out) {
1642                 if (t.countTokens() != 0) {
1643                     usage();
1644                 } else {
1645                     Universe u = VM.getVM().getUniverse();
1646                     out.println("Heap Parameters:");
1647                     u.heap().printOn(out);
1648                 }
1649             }
1650         },
1651         new ClhsdbCommand("verbose", "verbose true | false", true) {
1652             @Override
1653             public void doit(Tokens t, PrintStream out) {
1654                 if (t.countTokens() != 1) {
1655                     usage();
1656                 } else {
1657                     verboseExceptions = Boolean.valueOf(t.nextToken()).booleanValue();
1658                 }
1659             }
1660         },
1661         new ClhsdbCommand("assert", "assert true | false", true) {
1662             @Override
1663             public void doit(Tokens t, PrintStream out) {
1664                 if (t.countTokens() != 1) {
1665                     usage();
1666                 } else {
1667                     Assert.ASSERTS_ENABLED = Boolean.valueOf(t.nextToken()).booleanValue();
1668                 }
1669             }
1670         },
1671         new ClhsdbCommand("load_plugin", "load_plugin [path]", true) {
1672             @Override
1673             public void doit(Tokens t, PrintStream out) {
1674                 if (t.countTokens() != 1) {
1675                     usage();
1676                 } else {
1677                     registerCommand(Path.of(t.nextToken()));
1678                 }
1679             }
1680         },
1681     };
1682 
1683     private boolean verboseExceptions = false;
1684     private ArrayList history = new ArrayList();
1685     private HashMap commands = new HashMap();
1686     private boolean doEcho = false;
1687 
1688     private Command findCommand(String key) {
1689         return (Command)commands.get(key);
1690     }
1691 
1692     public void printPrompt() {
1693         out.print("hsdb> ");
1694     }
1695 
1696     private DebuggerInterface debugger;
1697     private HotSpotAgent agent;
1698     private JSJavaScriptEngine jsengine;
1699     private BufferedReader in;
1700     private PrintStream out;


1739                      this.getClass().getMethod("registerCommand",
1740                                 new Class[] {
1741                                      String.class, String.class, String.class
1742                                 }));
1743             } catch (NoSuchMethodException exp) {
1744                   // should not happen, see below...!!
1745                   exp.printStackTrace();
1746             }
1747             jsengine.start();
1748         }
1749         catch (Exception ex) {
1750             System.out.println("Warning! JS Engine can't start, some commands will not be available.");
1751             if (verboseExceptions) {
1752                 ex.printStackTrace(out);
1753             }
1754         }
1755         */
1756     }
1757 
1758     public void registerCommand(String cmd, String usage, final String func) {
1759         commands.put(cmd, new ClhsdbCommand(cmd, usage, false) {
1760                               @Override
1761                               public void doit(Tokens t, PrintStream out) {
1762                                   final int len = t.countTokens();
1763                                   Object[] args = new Object[len];
1764                                   for (int i = 0; i < len; i++) {
1765                                       args[i] = t.nextToken();
1766                                   }
1767                                   jsengine.call(func, args);
1768                               }
1769                           });
1770     }
1771 
1772     public void registerCommand(Path path) {
1773         Module saModule = this.getClass().getModule();
1774         ModuleLayer saLayer = saModule.getLayer();
1775 
1776         // Create new module for the path
1777         ModuleFinder finder = ModuleFinder.of(path);
1778         Set<String> moduleNames = finder.findAll()
1779                                         .stream()
1780                                         .map(r -> r.descriptor().name())
1781                                         .peek(m -> System.out.println("Module found: " + m))
1782                                         .collect(Collectors.toSet());
1783 
1784         Configuration conf = saLayer.configuration()
1785                                     .resolveAndBind(finder, ModuleFinder.of(), moduleNames);
1786         ModuleLayer layer = saLayer.defineModulesWithOneLoader(conf, saModule.getClassLoader());
1787 
1788         // Export all SA packages to the new module
1789         layer.modules()
1790              .stream()
1791              .forEach(m -> saModule.getPackages()
1792                                    .stream()
1793                                    .forEach(p -> saModule.addExports(p, m)));
1794 
1795         // Register command in the new module
1796         ServiceLoader.load(layer, Command.class)
1797                      .stream()
1798                      .map(ServiceLoader.Provider::get)
1799                      .peek(s -> System.out.println("Installing: " + s.name()))
1800                      .forEach(s -> commands.put(s.name(), s));
1801     }
1802 
1803     public void setOutput(PrintStream o) {
1804         out = o;
1805     }
1806 
1807     public void setErr(PrintStream e) {
1808         err = e;
1809     }
1810 
1811     public CommandProcessor(DebuggerInterface debugger, BufferedReader in, PrintStream out, PrintStream err) {
1812         this.debugger = debugger;
1813         this.agent = debugger.getAgent();
1814         this.in = in;
1815         this.out = out;
1816         this.err = err;
1817         for (int i = 0; i < commandList.length; i++) {
1818             Command c = commandList[i];
1819             if (commands.get(c.name()) != null) {
1820                 throw new InternalError(c.name() + " has multiple definitions");
1821             }
1822             commands.put(c.name(), c);
1823         }
1824         if (debugger.isAttached()) {
1825             postAttach();
1826         }
1827     }
1828 
1829 
1830     public void run(boolean prompt) {
1831         // Process interactive commands.
1832         while (!quit) {
1833             if (prompt) printPrompt();
1834             String ln = null;
1835             try {
1836                 ln = in.readLine();
1837             } catch (IOException e) {
1838             }
1839             if (ln == null) {
1840                 if (prompt) err.println("Input stream closed.");
1841                 return;
1842             }


1970                 } finally {
1971                     if (redirect != null) {
1972                         out = savedout;
1973                         redirect.close();
1974                     }
1975                 }
1976             }
1977         }
1978     }
1979 
1980     void executeCommand(Tokens args) {
1981         String cmd = args.nextToken();
1982 
1983         Command doit = findCommand(cmd);
1984 
1985         /*
1986          * Check for an unknown command
1987          */
1988         if (doit == null) {
1989             out.println("Unrecognized command.  Try help...");
1990         } else if (!debugger.isAttached() && !doit.okIfDisconnected()) {
1991             out.println("Command not valid until attached to a VM");
1992         } else {
1993             try {
1994                 doit.doit(args, out);
1995             } catch (Exception e) {
1996                 out.println("Error: " + e);
1997                 if (verboseExceptions) {
1998                     e.printStackTrace(out);
1999                 }
2000             }
2001         }
2002     }
2003 }
< prev index next >