Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java @ 2432:455328d90876
7029458: G1: Add newly-reclaimed regions to the beginning of the region free list, not the end
Summary: What the synopsis says.
Reviewed-by: jwilhelm, iveresov, johnc
author | tonyp |
---|---|
date | Tue, 29 Mar 2011 22:36:16 -0400 |
parents | 3582bf76420e |
children | 1d1603768966 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1385
diff
changeset
|
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1385
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1385
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1385
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot; | |
26 | |
27 import java.io.*; | |
28 import java.math.*; | |
29 import java.util.*; | |
30 import java.util.regex.*; | |
31 | |
32 import sun.jvm.hotspot.types.Type; | |
33 import sun.jvm.hotspot.types.Field; | |
34 import sun.jvm.hotspot.HotSpotTypeDataBase; | |
35 import sun.jvm.hotspot.types.basic.BasicType; | |
36 import sun.jvm.hotspot.types.CIntegerType; | |
37 import sun.jvm.hotspot.code.*; | |
38 import sun.jvm.hotspot.compiler.*; | |
39 import sun.jvm.hotspot.debugger.*; | |
40 import sun.jvm.hotspot.interpreter.*; | |
41 import sun.jvm.hotspot.memory.*; | |
42 import sun.jvm.hotspot.oops.*; | |
43 import sun.jvm.hotspot.runtime.*; | |
44 import sun.jvm.hotspot.utilities.*; | |
45 import sun.jvm.hotspot.utilities.soql.*; | |
46 import sun.jvm.hotspot.ui.classbrowser.*; | |
47 import sun.jvm.hotspot.ui.tree.*; | |
48 import sun.jvm.hotspot.tools.*; | |
49 import sun.jvm.hotspot.tools.ObjectHistogram; | |
50 import sun.jvm.hotspot.tools.StackTrace; | |
51 | |
52 public class CommandProcessor { | |
53 public abstract static class DebuggerInterface { | |
54 public abstract HotSpotAgent getAgent(); | |
55 public abstract boolean isAttached(); | |
56 public abstract void attach(String pid); | |
57 public abstract void attach(String java, String core); | |
58 public abstract void detach(); | |
59 public abstract void reattach(); | |
60 } | |
61 | |
62 static class Tokens { | |
63 final String input; | |
64 int i; | |
65 String[] tokens; | |
66 int length; | |
67 | |
68 String[] splitWhitespace(String cmd) { | |
69 String[] t = cmd.split("\\s"); | |
70 if (t.length == 1 && t[0].length() == 0) { | |
71 return new String[0]; | |
72 } | |
73 return t; | |
74 } | |
75 | |
76 void add(String s, ArrayList t) { | |
77 if (s.length() > 0) { | |
78 t.add(s); | |
79 } | |
80 } | |
81 | |
82 Tokens(String cmd) { | |
83 input = cmd; | |
84 | |
85 // check for quoting | |
86 int quote = cmd.indexOf('"'); | |
87 ArrayList t = new ArrayList(); | |
88 if (quote != -1) { | |
89 while (cmd.length() > 0) { | |
90 if (quote != -1) { | |
91 int endquote = cmd.indexOf('"', quote + 1); | |
92 if (endquote == -1) { | |
93 throw new RuntimeException("mismatched quotes: " + input); | |
94 } | |
95 | |
96 String before = cmd.substring(0, quote).trim(); | |
97 String quoted = cmd.substring(quote + 1, endquote); | |
98 cmd = cmd.substring(endquote + 1).trim(); | |
99 if (before.length() > 0) { | |
100 String[] w = splitWhitespace(before); | |
101 for (int i = 0; i < w.length; i++) { | |
102 add(w[i], t); | |
103 } | |
104 } | |
105 add(quoted, t); | |
106 quote = cmd.indexOf('"'); | |
107 } else { | |
108 String[] w = splitWhitespace(cmd); | |
109 for (int i = 0; i < w.length; i++) { | |
110 add(w[i], t); | |
111 } | |
112 cmd = ""; | |
113 | |
114 } | |
115 } | |
116 } else { | |
117 String[] w = splitWhitespace(cmd); | |
118 for (int i = 0; i < w.length; i++) { | |
119 add(w[i], t); | |
120 } | |
121 } | |
122 tokens = (String[])t.toArray(new String[0]); | |
123 i = 0; | |
124 length = tokens.length; | |
125 | |
126 //for (int i = 0; i < tokens.length; i++) { | |
127 // System.out.println("\"" + tokens[i] + "\""); | |
128 //} | |
129 } | |
130 | |
131 String nextToken() { | |
132 return tokens[i++]; | |
133 } | |
134 boolean hasMoreTokens() { | |
135 return i < length; | |
136 } | |
137 int countTokens() { | |
138 return length - i; | |
139 } | |
140 void trim(int n) { | |
141 if (length >= n) { | |
142 length -= n; | |
143 } else { | |
144 throw new IndexOutOfBoundsException(String.valueOf(n)); | |
145 } | |
146 } | |
147 String join(String sep) { | |
148 StringBuffer result = new StringBuffer(); | |
149 for (int w = i; w < length; w++) { | |
150 result.append(tokens[w]); | |
151 if (w + 1 < length) { | |
152 result.append(sep); | |
153 } | |
154 } | |
155 return result.toString(); | |
156 } | |
157 | |
158 String at(int i) { | |
159 if (i < 0 || i >= length) { | |
160 throw new IndexOutOfBoundsException(String.valueOf(i)); | |
161 } | |
162 return tokens[i]; | |
163 } | |
164 } | |
165 | |
166 | |
167 abstract class Command { | |
168 Command(String n, String u, boolean ok) { | |
169 name = n; | |
170 usage = u; | |
171 okIfDisconnected = ok; | |
172 } | |
173 | |
174 Command(String n, boolean ok) { | |
175 name = n; | |
176 usage = n; | |
177 okIfDisconnected = ok; | |
178 } | |
179 | |
180 final String name; | |
181 final String usage; | |
182 final boolean okIfDisconnected; | |
183 abstract void doit(Tokens t); | |
184 void usage() { | |
185 out.println("Usage: " + usage); | |
186 } | |
187 | |
188 void printOopValue(Oop oop) { | |
189 if (oop != null) { | |
190 Klass k = oop.getKlass(); | |
191 Symbol s = k.getName(); | |
192 if (s != null) { | |
193 out.print("Oop for " + s.asString() + " @ "); | |
194 } else { | |
195 out.print("Oop @ "); | |
196 } | |
197 Oop.printOopAddressOn(oop, out); | |
198 } else { | |
199 out.print("null"); | |
200 } | |
201 } | |
202 | |
203 void printNode(SimpleTreeNode node) { | |
204 int count = node.getChildCount(); | |
205 for (int i = 0; i < count; i++) { | |
206 try { | |
207 SimpleTreeNode field = node.getChild(i); | |
208 if (field instanceof OopTreeNodeAdapter) { | |
209 out.print(field); | |
210 out.print(" "); | |
211 printOopValue(((OopTreeNodeAdapter)field).getOop()); | |
212 out.println(); | |
213 } else { | |
214 out.println(field); | |
215 } | |
216 } catch (Exception e) { | |
217 out.println(); | |
218 out.println("Error: " + e); | |
219 if (verboseExceptions) { | |
220 e.printStackTrace(out); | |
221 } | |
222 } | |
223 } | |
224 } | |
225 } | |
226 | |
227 void quote(String s) { | |
228 if (s.indexOf(" ") == -1) { | |
229 out.print(s); | |
230 } else { | |
231 out.print("\""); | |
232 out.print(s); | |
233 out.print("\""); | |
234 } | |
235 } | |
236 | |
237 void dumpType(Type type) { | |
238 out.print("type "); | |
239 quote(type.getName()); | |
240 out.print(" "); | |
241 if (type.getSuperclass() != null) { | |
242 quote(type.getSuperclass().getName()); | |
243 out.print(" "); | |
244 } else { | |
245 out.print("null "); | |
246 } | |
247 out.print(type.isOopType()); | |
248 out.print(" "); | |
249 if (type.isCIntegerType()) { | |
250 out.print("true "); | |
251 out.print(((CIntegerType)type).isUnsigned()); | |
252 out.print(" "); | |
253 } else { | |
254 out.print("false false "); | |
255 } | |
256 out.print(type.getSize()); | |
257 out.println(); | |
258 } | |
259 | |
260 void dumpFields(Type type) { | |
261 Iterator i = type.getFields(); | |
262 while (i.hasNext()) { | |
263 Field f = (Field) i.next(); | |
264 out.print("field "); | |
265 quote(type.getName()); | |
266 out.print(" "); | |
267 out.print(f.getName()); | |
268 out.print(" "); | |
269 quote(f.getType().getName()); | |
270 out.print(" "); | |
271 out.print(f.isStatic()); | |
272 out.print(" "); | |
273 if (f.isStatic()) { | |
274 out.print("0 "); | |
275 out.print(f.getStaticFieldAddress()); | |
276 } else { | |
277 out.print(f.getOffset()); | |
278 out.print(" 0x0"); | |
279 } | |
280 out.println(); | |
281 } | |
282 } | |
283 | |
284 | |
285 Address lookup(String symbol) { | |
286 if (symbol.indexOf("::") != -1) { | |
287 String[] parts = symbol.split("::"); | |
288 StringBuffer mangled = new StringBuffer("__1c"); | |
289 for (int i = 0; i < parts.length; i++) { | |
290 int len = parts[i].length(); | |
291 if (len >= 26) { | |
292 mangled.append((char)('a' + (len / 26))); | |
293 len = len % 26; | |
294 } | |
295 mangled.append((char)('A' + len)); | |
296 mangled.append(parts[i]); | |
297 } | |
298 mangled.append("_"); | |
299 symbol = mangled.toString(); | |
300 } | |
301 return VM.getVM().getDebugger().lookup(null, symbol); | |
302 } | |
303 | |
304 Address parseAddress(String addr) { | |
305 return VM.getVM().getDebugger().parseAddress(addr); | |
306 } | |
307 | |
308 private final Command[] commandList = { | |
309 new Command("reattach", true) { | |
310 public void doit(Tokens t) { | |
311 int tokens = t.countTokens(); | |
312 if (tokens != 0) { | |
313 usage(); | |
314 return; | |
315 } | |
316 preAttach(); | |
317 debugger.reattach(); | |
318 postAttach(); | |
319 } | |
320 }, | |
321 new Command("attach", "attach pid | exec core", true) { | |
322 public void doit(Tokens t) { | |
323 int tokens = t.countTokens(); | |
324 if (tokens == 1) { | |
325 preAttach(); | |
326 debugger.attach(t.nextToken()); | |
327 postAttach(); | |
328 } else if (tokens == 2) { | |
329 preAttach(); | |
330 debugger.attach(t.nextToken(), t.nextToken()); | |
331 postAttach(); | |
332 } else { | |
333 usage(); | |
334 } | |
335 } | |
336 }, | |
337 new Command("detach", false) { | |
338 public void doit(Tokens t) { | |
339 if (t.countTokens() != 0) { | |
340 usage(); | |
341 } else { | |
342 debugger.detach(); | |
343 } | |
344 } | |
345 }, | |
346 new Command("examine", "examine [ address/count ] | [ address,address]", false) { | |
347 Pattern args1 = Pattern.compile("^(0x[0-9a-f]+)(/([0-9]*)([a-z]*))?$"); | |
348 Pattern args2 = Pattern.compile("^(0x[0-9a-f]+),(0x[0-9a-f]+)(/[a-z]*)?$"); | |
349 | |
350 String fill(Address a, int width) { | |
351 String s = "0x0"; | |
352 if (a != null) { | |
353 s = a.toString(); | |
354 } | |
355 if (s.length() != width) { | |
356 return s.substring(0, 2) + "000000000000000000000".substring(0, width - s.length()) + s.substring(2); | |
357 } | |
358 return s; | |
359 } | |
360 | |
361 public void doit(Tokens t) { | |
362 if (t.countTokens() != 1) { | |
363 usage(); | |
364 } else { | |
365 String arg = t.nextToken(); | |
366 Matcher m1 = args1.matcher(arg); | |
367 Matcher m2 = args2.matcher(arg); | |
368 Address start = null; | |
369 Address end = null; | |
370 String format = ""; | |
371 int formatSize = (int)VM.getVM().getAddressSize(); | |
372 | |
373 if (m1.matches()) { | |
374 start = VM.getVM().getDebugger().parseAddress(m1.group(1)); | |
375 int count = 1; | |
376 if (m1.group(2) != null) { | |
377 count = Integer.parseInt(m1.group(3)); | |
378 } | |
379 end = start.addOffsetTo(count * formatSize); | |
380 } else if (m2.matches()) { | |
381 start = VM.getVM().getDebugger().parseAddress(m2.group(1)); | |
382 end = VM.getVM().getDebugger().parseAddress(m2.group(2)); | |
383 } else { | |
384 usage(); | |
385 return; | |
386 } | |
387 int line = 80; | |
388 int formatWidth = formatSize * 8 / 4 + 2; | |
389 | |
390 out.print(fill(start, formatWidth)); | |
391 out.print(": "); | |
392 int width = line - formatWidth - 2; | |
393 | |
394 boolean needsPrintln = true; | |
395 while (start != null && start.lessThan(end)) { | |
396 Address val = start.getAddressAt(0); | |
397 out.print(fill(val, formatWidth)); | |
398 needsPrintln = true; | |
399 width -= formatWidth; | |
400 start = start.addOffsetTo(formatSize); | |
401 if (width <= formatWidth) { | |
402 out.println(); | |
403 needsPrintln = false; | |
404 if (start.lessThan(end)) { | |
405 out.print(fill(start, formatWidth)); | |
406 out.print(": "); | |
407 width = line - formatWidth - 2; | |
408 } | |
409 } else { | |
410 out.print(" "); | |
411 width -= 1; | |
412 } | |
413 } | |
414 if (needsPrintln) { | |
415 out.println(); | |
416 } | |
417 } | |
418 } | |
419 }, | |
420 new Command("findpc", "findpc address", false) { | |
421 public void doit(Tokens t) { | |
422 if (t.countTokens() != 1) { | |
423 usage(); | |
424 } else { | |
425 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
426 PointerLocation loc = PointerFinder.find(a); | |
427 loc.printOn(out); | |
428 } | |
429 } | |
430 }, | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
431 new Command("symbol", "symbol address", false) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
432 public void doit(Tokens t) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
433 if (t.countTokens() != 1) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
434 usage(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
435 } else { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
436 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
437 Symbol.create(a).printValueOn(out); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
438 out.println(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
439 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
440 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
441 }, |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
442 new Command("symboltable", "symboltable name", false) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
443 public void doit(Tokens t) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
444 if (t.countTokens() != 1) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
445 usage(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
446 } else { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
447 out.println(SymbolTable.getTheTable().probe(t.nextToken())); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
448 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
449 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
450 }, |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
451 new Command("symboldump", "symboldump", false) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
452 public void doit(Tokens t) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
453 SymbolTable.getTheTable().symbolsDo(new SymbolTable.SymbolVisitor() { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
454 public void visit(Symbol sym) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
455 sym.printValueOn(out); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
456 out.println(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
457 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
458 }); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
459 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
460 }, |
0 | 461 new Command("flags", "flags [ flag ]", false) { |
462 public void doit(Tokens t) { | |
463 int tokens = t.countTokens(); | |
464 if (tokens != 0 && tokens != 1) { | |
465 usage(); | |
466 } else { | |
467 String name = tokens > 0 ? t.nextToken() : null; | |
468 | |
469 VM.Flag[] flags = VM.getVM().getCommandLineFlags(); | |
470 if (flags == null) { | |
471 out.println("Command Flag info not available (use 1.4.1_03 or later)!"); | |
472 } else { | |
473 boolean printed = false; | |
474 for (int f = 0; f < flags.length; f++) { | |
475 VM.Flag flag = flags[f]; | |
476 if (name == null || flag.getName().equals(name)) { | |
477 out.println(flag.getName() + " = " + flag.getValue()); | |
478 printed = true; | |
479 } | |
480 } | |
481 if (name != null && !printed) { | |
482 out.println("Couldn't find flag: " + name); | |
483 } | |
484 } | |
485 } | |
486 } | |
487 }, | |
488 new Command("help", "help [ command ]", true) { | |
489 public void doit(Tokens t) { | |
490 int tokens = t.countTokens(); | |
491 Command cmd = null; | |
492 if (tokens == 1) { | |
493 cmd = findCommand(t.nextToken()); | |
494 } | |
495 | |
496 if (cmd != null) { | |
497 cmd.usage(); | |
498 } else if (tokens == 0) { | |
499 out.println("Available commands:"); | |
500 Object[] keys = commands.keySet().toArray(); | |
501 Arrays.sort(keys, new Comparator() { | |
502 public int compare(Object o1, Object o2) { | |
503 return o1.toString().compareTo(o2.toString()); | |
504 } | |
505 }); | |
506 for (int i = 0; i < keys.length; i++) { | |
507 out.print(" "); | |
508 out.println(((Command)commands.get(keys[i])).usage); | |
509 } | |
510 } | |
511 } | |
512 }, | |
513 new Command("history", "history", true) { | |
514 public void doit(Tokens t) { | |
515 int tokens = t.countTokens(); | |
516 if (tokens != 0 && (tokens != 1 || !t.nextToken().equals("-h"))) { | |
517 usage(); | |
518 return; | |
519 } | |
520 boolean printIndex = tokens == 0; | |
521 for (int i = 0; i < history.size(); i++) { | |
522 if (printIndex) out.print(i + " "); | |
523 out.println(history.get(i)); | |
524 } | |
525 } | |
526 }, | |
1385 | 527 new Command("revptrs", "revptrs address", false) { |
528 public void doit(Tokens t) { | |
529 int tokens = t.countTokens(); | |
530 if (tokens != 1 && (tokens != 2 || !t.nextToken().equals("-c"))) { | |
531 usage(); | |
532 return; | |
533 } | |
534 boolean chase = tokens == 2; | |
535 ReversePtrs revptrs = VM.getVM().getRevPtrs(); | |
536 if (revptrs == null) { | |
537 out.println("Computing reverse pointers..."); | |
538 ReversePtrsAnalysis analysis = new ReversePtrsAnalysis(); | |
539 final boolean[] complete = new boolean[1]; | |
540 HeapProgressThunk thunk = new HeapProgressThunk() { | |
541 public void heapIterationFractionUpdate(double d) {} | |
542 public synchronized void heapIterationComplete() { | |
543 complete[0] = true; | |
544 notify(); | |
545 } | |
546 }; | |
547 analysis.setHeapProgressThunk(thunk); | |
548 analysis.run(); | |
549 while (!complete[0]) { | |
550 synchronized (thunk) { | |
551 try { | |
552 thunk.wait(); | |
553 } catch (Exception e) { | |
554 } | |
555 } | |
556 } | |
557 revptrs = VM.getVM().getRevPtrs(); | |
558 out.println("Done."); | |
559 } | |
560 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
561 if (VM.getVM().getUniverse().heap().isInReserved(a)) { | |
562 OopHandle handle = a.addOffsetToAsOopHandle(0); | |
563 Oop oop = VM.getVM().getObjectHeap().newOop(handle); | |
564 ArrayList ptrs = revptrs.get(oop); | |
565 if (ptrs == null) { | |
566 out.println("no live references to " + a); | |
567 } else { | |
568 if (chase) { | |
569 while (ptrs.size() == 1) { | |
570 LivenessPathElement e = (LivenessPathElement)ptrs.get(0); | |
571 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
572 Oop.printOopValueOn(e.getObj(), new PrintStream(bos)); | |
573 out.println(bos.toString()); | |
574 ptrs = revptrs.get(e.getObj()); | |
575 } | |
576 } else { | |
577 for (int i = 0; i < ptrs.size(); i++) { | |
578 LivenessPathElement e = (LivenessPathElement)ptrs.get(i); | |
579 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
580 Oop.printOopValueOn(e.getObj(), new PrintStream(bos)); | |
581 out.println(bos.toString()); | |
582 oop = e.getObj(); | |
583 } | |
584 } | |
585 } | |
586 } | |
587 } | |
588 }, | |
0 | 589 new Command("inspect", "inspect expression", false) { |
590 public void doit(Tokens t) { | |
591 if (t.countTokens() != 1) { | |
592 usage(); | |
593 } else { | |
594 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
595 SimpleTreeNode node = null; | |
596 if (VM.getVM().getUniverse().heap().isInReserved(a)) { | |
597 OopHandle handle = a.addOffsetToAsOopHandle(0); | |
598 Oop oop = VM.getVM().getObjectHeap().newOop(handle); | |
599 node = new OopTreeNodeAdapter(oop, null); | |
600 | |
601 out.println("instance of " + node.getValue() + " @ " + a + | |
602 " (size = " + oop.getObjectSize() + ")"); | |
603 } else if (VM.getVM().getCodeCache().contains(a)) { | |
604 CodeBlob blob = VM.getVM().getCodeCache().findBlobUnsafe(a); | |
605 a = blob.headerBegin(); | |
606 } | |
607 if (node == null) { | |
608 Type type = VM.getVM().getTypeDataBase().guessTypeForAddress(a); | |
609 if (type != null) { | |
610 out.println("Type is " + type.getName() + " (size of " + type.getSize() + ")"); | |
611 node = new CTypeTreeNodeAdapter(a, type, null); | |
612 } | |
613 } | |
614 if (node != null) { | |
615 printNode(node); | |
616 } | |
617 } | |
618 } | |
619 }, | |
620 new Command("jhisto", "jhisto", false) { | |
621 public void doit(Tokens t) { | |
622 ObjectHistogram histo = new ObjectHistogram(); | |
623 histo.run(out, err); | |
624 } | |
625 }, | |
626 new Command("jstack", "jstack [-v]", false) { | |
627 public void doit(Tokens t) { | |
628 boolean verbose = false; | |
629 if (t.countTokens() > 0 && t.nextToken().equals("-v")) { | |
630 verbose = true; | |
631 } | |
632 StackTrace jstack = new StackTrace(verbose, true); | |
633 jstack.run(out); | |
634 } | |
635 }, | |
636 new Command("print", "print expression", false) { | |
637 public void doit(Tokens t) { | |
638 if (t.countTokens() != 1) { | |
639 usage(); | |
640 } else { | |
641 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
642 HTMLGenerator gen = new HTMLGenerator(false); | |
643 out.println(gen.genHTML(a)); | |
644 } | |
645 } | |
646 }, | |
647 new Command("printas", "printas type expression", false) { | |
648 public void doit(Tokens t) { | |
649 if (t.countTokens() != 2) { | |
650 usage(); | |
651 } else { | |
652 Type type = agent.getTypeDataBase().lookupType(t.nextToken()); | |
653 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
654 CTypeTreeNodeAdapter node = new CTypeTreeNodeAdapter(a, type, null); | |
655 | |
656 out.println("pointer to " + type + " @ " + a + | |
657 " (size = " + type.getSize() + ")"); | |
658 printNode(node); | |
659 } | |
660 } | |
661 }, | |
662 new Command("printstatics", "printstatics [ type ]", false) { | |
663 public void doit(Tokens t) { | |
664 if (t.countTokens() > 1) { | |
665 usage(); | |
666 } else { | |
667 if (t.countTokens() == 0) { | |
668 out.println("All known static fields"); | |
669 printNode(new CTypeTreeNodeAdapter(agent.getTypeDataBase().getTypes())); | |
670 } else { | |
671 Type type = agent.getTypeDataBase().lookupType(t.nextToken()); | |
672 out.println("Static fields of " + type.getName()); | |
673 printNode(new CTypeTreeNodeAdapter(type)); | |
674 } | |
675 } | |
676 } | |
677 }, | |
678 new Command("pmap", "pmap", false) { | |
679 public void doit(Tokens t) { | |
680 PMap pmap = new PMap(); | |
681 pmap.run(out, debugger.getAgent().getDebugger()); | |
682 } | |
683 }, | |
684 new Command("pstack", "pstack [-v]", false) { | |
685 public void doit(Tokens t) { | |
686 boolean verbose = false; | |
687 if (t.countTokens() > 0 && t.nextToken().equals("-v")) { | |
688 verbose = true; | |
689 } | |
690 PStack pstack = new PStack(verbose, true); | |
691 pstack.run(out, debugger.getAgent().getDebugger()); | |
692 } | |
693 }, | |
694 new Command("quit", true) { | |
695 public void doit(Tokens t) { | |
696 if (t.countTokens() != 0) { | |
697 usage(); | |
698 } else { | |
699 debugger.detach(); | |
700 System.exit(0); | |
701 } | |
702 } | |
703 }, | |
704 new Command("echo", "echo [ true | false ]", true) { | |
705 public void doit(Tokens t) { | |
706 if (t.countTokens() == 0) { | |
707 out.println("echo is " + doEcho); | |
708 } else if (t.countTokens() == 1) { | |
709 doEcho = Boolean.valueOf(t.nextToken()).booleanValue(); | |
710 } else { | |
711 usage(); | |
712 } | |
713 } | |
714 }, | |
715 new Command("versioncheck", "versioncheck [ true | false ]", true) { | |
716 public void doit(Tokens t) { | |
717 if (t.countTokens() == 0) { | |
718 out.println("versioncheck is " + | |
719 (System.getProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck") == null)); | |
720 } else if (t.countTokens() == 1) { | |
721 if (Boolean.valueOf(t.nextToken()).booleanValue()) { | |
722 System.setProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck", null); | |
723 } else { | |
724 System.setProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck", "true"); | |
725 } | |
726 } else { | |
727 usage(); | |
728 } | |
729 } | |
730 }, | |
731 new Command("scanoops", "scanoops start end [ type ]", false) { | |
732 public void doit(Tokens t) { | |
733 if (t.countTokens() != 2 && t.countTokens() != 3) { | |
734 usage(); | |
735 } else { | |
736 long stride = VM.getVM().getAddressSize(); | |
737 Address base = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
738 Address end = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
739 Klass klass = null; | |
740 if (t.countTokens() == 1) { | |
741 klass = SystemDictionaryHelper.findInstanceKlass(t.nextToken()); | |
742 } | |
743 while (base != null && base.lessThan(end)) { | |
744 long step = stride; | |
745 OopHandle handle = base.addOffsetToAsOopHandle(0); | |
746 if (RobustOopDeterminator.oopLooksValid(handle)) { | |
747 try { | |
748 Oop oop = VM.getVM().getObjectHeap().newOop(handle); | |
749 if (klass == null || oop.getKlass().isSubtypeOf(klass)) | |
750 out.println(handle.toString() + " " + oop.getKlass().getName().asString()); | |
751 step = oop.getObjectSize(); | |
752 } catch (UnknownOopException ex) { | |
753 // ok | |
754 } catch (RuntimeException ex) { | |
755 ex.printStackTrace(); | |
756 } | |
757 } | |
758 base = base.addOffsetTo(step); | |
759 } | |
760 } | |
761 } | |
762 }, | |
763 new Command("field", "field [ type [ name fieldtype isStatic offset address ] ]", true) { | |
764 public void doit(Tokens t) { | |
765 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) { | |
766 usage(); | |
767 return; | |
768 } | |
769 if (t.countTokens() == 1) { | |
770 Type type = agent.getTypeDataBase().lookupType(t.nextToken()); | |
771 dumpFields(type); | |
772 } else if (t.countTokens() == 0) { | |
773 Iterator i = agent.getTypeDataBase().getTypes(); | |
774 while (i.hasNext()) { | |
775 dumpFields((Type)i.next()); | |
776 } | |
777 } else { | |
778 BasicType containingType = (BasicType)agent.getTypeDataBase().lookupType(t.nextToken()); | |
779 | |
780 String fieldName = t.nextToken(); | |
781 | |
782 // The field's Type must already be in the database -- no exceptions | |
783 Type fieldType = agent.getTypeDataBase().lookupType(t.nextToken()); | |
784 | |
785 boolean isStatic = Boolean.valueOf(t.nextToken()).booleanValue(); | |
786 long offset = Long.parseLong(t.nextToken()); | |
787 Address staticAddress = parseAddress(t.nextToken()); | |
788 if (isStatic && staticAddress == null) { | |
789 staticAddress = lookup(containingType.getName() + "::" + fieldName); | |
790 } | |
791 | |
792 // check to see if the field already exists | |
793 Iterator i = containingType.getFields(); | |
794 while (i.hasNext()) { | |
795 Field f = (Field) i.next(); | |
796 if (f.getName().equals(fieldName)) { | |
797 if (f.isStatic() != isStatic) { | |
798 throw new RuntimeException("static/nonstatic mismatch: " + t.input); | |
799 } | |
800 if (!isStatic) { | |
801 if (f.getOffset() != offset) { | |
802 throw new RuntimeException("bad redefinition of field offset: " + t.input); | |
803 } | |
804 } else { | |
805 if (!f.getStaticFieldAddress().equals(staticAddress)) { | |
806 throw new RuntimeException("bad redefinition of field location: " + t.input); | |
807 } | |
808 } | |
809 if (f.getType() != fieldType) { | |
810 throw new RuntimeException("bad redefinition of field type: " + t.input); | |
811 } | |
812 return; | |
813 } | |
814 } | |
815 | |
816 // Create field by type | |
817 HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase(); | |
818 db.createField(containingType, | |
819 fieldName, fieldType, | |
820 isStatic, | |
821 offset, | |
822 staticAddress); | |
823 | |
824 } | |
825 } | |
826 | |
827 }, | |
828 new Command("tokenize", "tokenize ...", true) { | |
829 public void doit(Tokens t) { | |
830 while (t.hasMoreTokens()) { | |
831 out.println("\"" + t.nextToken() + "\""); | |
832 } | |
833 } | |
834 }, | |
835 new Command("type", "type [ type [ name super isOop isInteger isUnsigned size ] ]", true) { | |
836 public void doit(Tokens t) { | |
837 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) { | |
838 usage(); | |
839 return; | |
840 } | |
841 if (t.countTokens() == 6) { | |
842 String typeName = t.nextToken(); | |
843 String superclassName = t.nextToken(); | |
844 if (superclassName.equals("null")) { | |
845 superclassName = null; | |
846 } | |
847 boolean isOop = Boolean.valueOf(t.nextToken()).booleanValue(); | |
848 boolean isInteger = Boolean.valueOf(t.nextToken()).booleanValue(); | |
849 boolean isUnsigned = Boolean.valueOf(t.nextToken()).booleanValue(); | |
850 long size = Long.parseLong(t.nextToken()); | |
851 | |
852 BasicType type = null; | |
853 try { | |
854 type = (BasicType)agent.getTypeDataBase().lookupType(typeName); | |
855 } catch (RuntimeException e) { | |
856 } | |
857 if (type != null) { | |
858 if (type.isOopType() != isOop) { | |
859 throw new RuntimeException("oop mismatch in type definition: " + t.input); | |
860 } | |
861 if (type.isCIntegerType() != isInteger) { | |
862 throw new RuntimeException("integer type mismatch in type definition: " + t.input); | |
863 } | |
864 if (type.isCIntegerType() && (((CIntegerType)type).isUnsigned()) != isUnsigned) { | |
865 throw new RuntimeException("unsigned mismatch in type definition: " + t.input); | |
866 } | |
867 if (type.getSuperclass() == null) { | |
868 if (superclassName != null) { | |
869 if (type.getSize() == -1) { | |
870 type.setSuperclass(agent.getTypeDataBase().lookupType(superclassName)); | |
871 } else { | |
872 throw new RuntimeException("unexpected superclass in type definition: " + t.input); | |
873 } | |
874 } | |
875 } else { | |
876 if (superclassName == null) { | |
877 throw new RuntimeException("missing superclass in type definition: " + t.input); | |
878 } | |
879 if (!type.getSuperclass().getName().equals(superclassName)) { | |
880 throw new RuntimeException("incorrect superclass in type definition: " + t.input); | |
881 } | |
882 } | |
883 if (type.getSize() != size) { | |
884 if (type.getSize() == -1) { | |
885 type.setSize(size); | |
886 } | |
887 throw new RuntimeException("size mismatch in type definition: " + t.input); | |
888 } | |
889 return; | |
890 } | |
891 | |
892 // Create type | |
893 HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase(); | |
894 db.createType(typeName, superclassName, isOop, isInteger, isUnsigned, size); | |
895 } else if (t.countTokens() == 1) { | |
896 Type type = agent.getTypeDataBase().lookupType(t.nextToken()); | |
897 dumpType(type); | |
898 } else { | |
899 Iterator i = agent.getTypeDataBase().getTypes(); | |
1385 | 900 // Make sure the types are emitted in an order than can be read back in |
901 HashSet emitted = new HashSet(); | |
902 Stack pending = new Stack(); | |
0 | 903 while (i.hasNext()) { |
1385 | 904 Type n = (Type)i.next(); |
905 if (emitted.contains(n.getName())) { | |
906 continue; | |
907 } | |
908 | |
909 while (n != null && !emitted.contains(n.getName())) { | |
910 pending.push(n); | |
911 n = n.getSuperclass(); | |
912 } | |
913 while (!pending.empty()) { | |
914 n = (Type)pending.pop(); | |
915 dumpType(n); | |
916 emitted.add(n.getName()); | |
917 } | |
0 | 918 } |
919 } | |
920 } | |
921 | |
922 }, | |
923 new Command("source", "source filename", true) { | |
924 public void doit(Tokens t) { | |
925 if (t.countTokens() != 1) { | |
926 usage(); | |
927 return; | |
928 } | |
929 String file = t.nextToken(); | |
930 BufferedReader savedInput = in; | |
931 try { | |
932 BufferedReader input = new BufferedReader(new InputStreamReader(new FileInputStream(file))); | |
933 in = input; | |
934 run(false); | |
935 } catch (Exception e) { | |
936 out.println("Error: " + e); | |
937 if (verboseExceptions) { | |
938 e.printStackTrace(out); | |
939 } | |
940 } finally { | |
941 in = savedInput; | |
942 } | |
943 | |
944 } | |
945 }, | |
1385 | 946 new Command("search", "search [ heap | perm | rawheap | codecache | threads ] value", false) { |
0 | 947 public void doit(Tokens t) { |
948 if (t.countTokens() != 2) { | |
949 usage(); | |
1385 | 950 return; |
951 } | |
952 String type = t.nextToken(); | |
953 final Address value = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
954 final long stride = VM.getVM().getAddressSize(); | |
955 if (type.equals("threads")) { | |
956 Threads threads = VM.getVM().getThreads(); | |
957 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { | |
958 Address base = thread.getBaseOfStackPointer(); | |
959 Address end = thread.getLastJavaSP(); | |
960 if (end == null) continue; | |
961 if (end.lessThan(base)) { | |
962 Address tmp = base; | |
963 base = end; | |
964 end = tmp; | |
965 } | |
966 out.println("Searching " + base + " " + end); | |
967 while (base != null && base.lessThan(end)) { | |
968 Address val = base.getAddressAt(0); | |
969 if (AddressOps.equal(val, value)) { | |
970 out.println(base); | |
971 } | |
972 base = base.addOffsetTo(stride); | |
973 } | |
974 } | |
975 } else if (type.equals("rawheap")) { | |
976 RawHeapVisitor iterator = new RawHeapVisitor() { | |
977 public void prologue(long used) { | |
0 | 978 } |
1385 | 979 |
980 public void visitAddress(Address addr) { | |
981 Address val = addr.getAddressAt(0); | |
0 | 982 if (AddressOps.equal(val, value)) { |
1385 | 983 out.println("found at " + addr); |
0 | 984 } |
1385 | 985 } |
986 public void visitCompOopAddress(Address addr) { | |
987 Address val = addr.getCompOopAddressAt(0); | |
988 if (AddressOps.equal(val, value)) { | |
989 out.println("found at " + addr); | |
990 } | |
0 | 991 } |
1385 | 992 public void epilogue() { |
993 } | |
994 }; | |
995 VM.getVM().getObjectHeap().iterateRaw(iterator); | |
996 } else if (type.equals("heap") || type.equals("perm")) { | |
997 HeapVisitor iterator = new DefaultHeapVisitor() { | |
998 public boolean doObj(Oop obj) { | |
999 int index = 0; | |
1000 Address start = obj.getHandle(); | |
1001 long end = obj.getObjectSize(); | |
1002 while (index < end) { | |
1003 Address val = start.getAddressAt(index); | |
0 | 1004 if (AddressOps.equal(val, value)) { |
1385 | 1005 out.println("found in " + obj.getHandle()); |
1006 break; | |
0 | 1007 } |
1385 | 1008 index += 4; |
0 | 1009 } |
1385 | 1010 return false; |
1011 } | |
1012 }; | |
1013 if (type.equals("heap")) { | |
1014 VM.getVM().getObjectHeap().iterate(iterator); | |
1015 } else { | |
1016 VM.getVM().getObjectHeap().iteratePerm(iterator); | |
1017 } | |
1018 } else if (type.equals("codecache")) { | |
1019 CodeCacheVisitor v = new CodeCacheVisitor() { | |
1020 public void prologue(Address start, Address end) { | |
1021 } | |
1022 public void visit(CodeBlob blob) { | |
1023 boolean printed = false; | |
1024 Address base = blob.getAddress(); | |
1025 Address end = base.addOffsetTo(blob.getSize()); | |
1026 while (base != null && base.lessThan(end)) { | |
1027 Address val = base.getAddressAt(0); | |
1028 if (AddressOps.equal(val, value)) { | |
1029 if (!printed) { | |
1030 printed = true; | |
1031 blob.printOn(out); | |
0 | 1032 } |
1385 | 1033 out.println("found at " + base + "\n"); |
0 | 1034 } |
1385 | 1035 base = base.addOffsetTo(stride); |
0 | 1036 } |
1385 | 1037 } |
1038 public void epilogue() { | |
1039 } | |
0 | 1040 |
1041 | |
1385 | 1042 }; |
1043 VM.getVM().getCodeCache().iterate(v); | |
0 | 1044 |
1045 } | |
1046 } | |
1047 }, | |
1040
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1048 new Command("dumpcodecache", "dumpcodecache", false) { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1049 public void doit(Tokens t) { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1050 if (t.countTokens() != 0) { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1051 usage(); |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1052 } else { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1053 final PrintStream fout = out; |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1054 final HTMLGenerator gen = new HTMLGenerator(false); |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1055 CodeCacheVisitor v = new CodeCacheVisitor() { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1056 public void prologue(Address start, Address end) { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1057 } |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1058 public void visit(CodeBlob blob) { |
1748 | 1059 fout.println(gen.genHTML(blob.contentBegin())); |
1040
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1060 } |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1061 public void epilogue() { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1062 } |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1063 |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1064 |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1065 }; |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1066 VM.getVM().getCodeCache().iterate(v); |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1067 } |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1068 } |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1069 }, |
0 | 1070 new Command("where", "where { -a | id }", false) { |
1071 public void doit(Tokens t) { | |
1072 if (t.countTokens() != 1) { | |
1073 usage(); | |
1074 } else { | |
1075 String name = t.nextToken(); | |
1076 Threads threads = VM.getVM().getThreads(); | |
1077 boolean all = name.equals("-a"); | |
1078 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { | |
1079 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
1080 thread.printThreadIDOn(new PrintStream(bos)); | |
1081 if (all || bos.toString().equals(name)) { | |
1385 | 1082 out.println(bos.toString() + " = " + thread.getAddress()); |
0 | 1083 HTMLGenerator gen = new HTMLGenerator(false); |
1385 | 1084 try { |
1085 out.println(gen.genHTMLForJavaStackTrace(thread)); | |
1086 } catch (Exception e) { | |
1087 err.println("Error: " + e); | |
1088 if (verboseExceptions) { | |
1089 e.printStackTrace(err); | |
1090 } | |
1091 } | |
0 | 1092 if (!all) return; |
1093 } | |
1094 } | |
1095 if (!all) out.println("Couldn't find thread " + name); | |
1096 } | |
1097 } | |
1098 }, | |
1385 | 1099 new Command("thread", "thread { -a | id }", false) { |
1100 public void doit(Tokens t) { | |
1101 if (t.countTokens() != 1) { | |
1102 usage(); | |
1103 } else { | |
1104 String name = t.nextToken(); | |
1105 Threads threads = VM.getVM().getThreads(); | |
1106 boolean all = name.equals("-a"); | |
1107 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { | |
1108 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
1109 thread.printThreadIDOn(new PrintStream(bos)); | |
1110 if (all || bos.toString().equals(name)) { | |
1111 out.println(bos.toString() + " = " + thread.getAddress()); | |
1112 if (!all) return; | |
1113 } | |
1114 } | |
1115 out.println("Couldn't find thread " + name); | |
1116 } | |
1117 } | |
1118 }, | |
0 | 1119 |
1120 new Command("threads", false) { | |
1121 public void doit(Tokens t) { | |
1122 if (t.countTokens() != 0) { | |
1123 usage(); | |
1124 } else { | |
1125 Threads threads = VM.getVM().getThreads(); | |
1126 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { | |
1127 thread.printThreadIDOn(out); | |
1128 out.println(" " + thread.getThreadName()); | |
1129 } | |
1130 } | |
1131 } | |
1132 }, | |
1133 | |
1134 new Command("livenmethods", false) { | |
1135 public void doit(Tokens t) { | |
1136 if (t.countTokens() != 0) { | |
1137 usage(); | |
1138 } else { | |
1139 ArrayList nmethods = new ArrayList(); | |
1140 Threads threads = VM.getVM().getThreads(); | |
1141 HTMLGenerator gen = new HTMLGenerator(false); | |
1142 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { | |
1143 try { | |
1144 for (JavaVFrame vf = thread.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) { | |
1145 if (vf instanceof CompiledVFrame) { | |
1146 NMethod c = ((CompiledVFrame)vf).getCode(); | |
1147 if (!nmethods.contains(c)) { | |
1148 nmethods.add(c); | |
1149 out.println(gen.genHTML(c)); | |
1150 } | |
1151 } | |
1152 } | |
1153 } catch (Exception e) { | |
1154 e.printStackTrace(); | |
1155 } | |
1156 } | |
1157 } | |
1158 } | |
1159 }, | |
1160 new Command("universe", false) { | |
1161 public void doit(Tokens t) { | |
1162 if (t.countTokens() != 0) { | |
1163 usage(); | |
1164 } else { | |
1165 Universe u = VM.getVM().getUniverse(); | |
1166 out.println("Heap Parameters:"); | |
1167 u.heap().printOn(out); | |
1168 } | |
1169 } | |
1170 }, | |
1171 new Command("verbose", "verbose true | false", true) { | |
1172 public void doit(Tokens t) { | |
1173 if (t.countTokens() != 1) { | |
1174 usage(); | |
1175 } else { | |
1176 verboseExceptions = Boolean.valueOf(t.nextToken()).booleanValue(); | |
1177 } | |
1178 } | |
1179 }, | |
1180 new Command("assert", "assert true | false", true) { | |
1181 public void doit(Tokens t) { | |
1182 if (t.countTokens() != 1) { | |
1183 usage(); | |
1184 } else { | |
1185 Assert.ASSERTS_ENABLED = Boolean.valueOf(t.nextToken()).booleanValue(); | |
1186 } | |
1187 } | |
1188 }, | |
1189 }; | |
1190 | |
1191 private boolean verboseExceptions = false; | |
1192 private ArrayList history = new ArrayList(); | |
1193 private HashMap commands = new HashMap(); | |
1194 private boolean doEcho = false; | |
1195 | |
1196 private Command findCommand(String key) { | |
1197 return (Command)commands.get(key); | |
1198 } | |
1199 | |
1200 public void printPrompt() { | |
1201 out.print("hsdb> "); | |
1202 } | |
1203 | |
1204 private DebuggerInterface debugger; | |
1205 private HotSpotAgent agent; | |
1206 private JSJavaScriptEngine jsengine; | |
1207 private BufferedReader in; | |
1208 private PrintStream out; | |
1209 private PrintStream err; | |
1210 | |
1211 // called before debuggee attach | |
1212 private void preAttach() { | |
1213 // nothing for now.. | |
1214 } | |
1215 | |
1216 // called after debuggee attach | |
1217 private void postAttach() { | |
1218 // create JavaScript engine and start it | |
1219 jsengine = new JSJavaScriptEngine() { | |
1220 private ObjectReader reader = new ObjectReader(); | |
1221 private JSJavaFactory factory = new JSJavaFactoryImpl(); | |
1222 public ObjectReader getObjectReader() { | |
1223 return reader; | |
1224 } | |
1225 public JSJavaFactory getJSJavaFactory() { | |
1226 return factory; | |
1227 } | |
1228 protected void quit() { | |
1229 debugger.detach(); | |
1230 System.exit(0); | |
1231 } | |
1232 protected BufferedReader getInputReader() { | |
1233 return in; | |
1234 } | |
1235 protected PrintStream getOutputStream() { | |
1236 return out; | |
1237 } | |
1238 protected PrintStream getErrorStream() { | |
1239 return err; | |
1240 } | |
1241 }; | |
1242 try { | |
1243 jsengine.defineFunction(this, | |
1244 this.getClass().getMethod("registerCommand", | |
1245 new Class[] { | |
1246 String.class, String.class, String.class | |
1247 })); | |
1248 } catch (NoSuchMethodException exp) { | |
1249 // should not happen, see below...!! | |
1250 exp.printStackTrace(); | |
1251 } | |
1252 jsengine.start(); | |
1253 } | |
1254 | |
1255 public void registerCommand(String cmd, String usage, final String func) { | |
1256 commands.put(cmd, new Command(cmd, usage, false) { | |
1257 public void doit(Tokens t) { | |
1258 final int len = t.countTokens(); | |
1259 Object[] args = new Object[len]; | |
1260 for (int i = 0; i < len; i++) { | |
1261 args[i] = t.nextToken(); | |
1262 } | |
1263 jsengine.call(func, args); | |
1264 } | |
1265 }); | |
1266 } | |
1267 | |
1268 public void setOutput(PrintStream o) { | |
1269 out = o; | |
1270 } | |
1271 | |
1272 public void setErr(PrintStream e) { | |
1273 err = e; | |
1274 } | |
1275 | |
1276 public CommandProcessor(DebuggerInterface debugger, BufferedReader in, PrintStream out, PrintStream err) { | |
1277 this.debugger = debugger; | |
1278 this.agent = debugger.getAgent(); | |
1279 this.in = in; | |
1280 this.out = out; | |
1281 this.err = err; | |
1282 for (int i = 0; i < commandList.length; i++) { | |
1283 Command c = commandList[i]; | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
1284 if (commands.get(c.name) != null) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
1285 throw new InternalError(c.name + " has multiple definitions"); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
1286 } |
0 | 1287 commands.put(c.name, c); |
1288 } | |
1289 if (debugger.isAttached()) { | |
1290 postAttach(); | |
1291 } | |
1292 } | |
1293 | |
1294 | |
1295 public void run(boolean prompt) { | |
1296 // Process interactive commands. | |
1297 while (true) { | |
1298 if (prompt) printPrompt(); | |
1299 String ln = null; | |
1300 try { | |
1301 ln = in.readLine(); | |
1302 } catch (IOException e) { | |
1303 } | |
1304 if (ln == null) { | |
1305 if (prompt) err.println("Input stream closed."); | |
1306 return; | |
1307 } | |
1308 | |
1309 executeCommand(ln); | |
1310 } | |
1311 } | |
1312 | |
1385 | 1313 static Pattern historyPattern = Pattern.compile("((!\\*)|(!\\$)|(!!-?)|(!-?[0-9][0-9]*)|(![a-zA-Z][^ ]*))"); |
0 | 1314 |
1315 public void executeCommand(String ln) { | |
1316 if (ln.indexOf('!') != -1) { | |
1317 int size = history.size(); | |
1318 if (size == 0) { | |
1319 ln = ""; | |
1320 err.println("History is empty"); | |
1321 } else { | |
1322 StringBuffer result = new StringBuffer(); | |
1323 Matcher m = historyPattern.matcher(ln); | |
1324 int start = 0; | |
1325 while (m.find()) { | |
1326 if (m.start() > start) { | |
1327 result.append(ln.substring(start, m.start() - start)); | |
1328 } | |
1329 start = m.end(); | |
1330 | |
1331 String cmd = m.group(); | |
1332 if (cmd.equals("!!")) { | |
1333 result.append((String)history.get(history.size() - 1)); | |
1334 } else if (cmd.equals("!!-")) { | |
1335 Tokens item = new Tokens((String)history.get(history.size() - 1)); | |
1336 item.trim(1); | |
1337 result.append(item.join(" ")); | |
1338 } else if (cmd.equals("!*")) { | |
1339 Tokens item = new Tokens((String)history.get(history.size() - 1)); | |
1340 item.nextToken(); | |
1341 result.append(item.join(" ")); | |
1342 } else if (cmd.equals("!$")) { | |
1343 Tokens item = new Tokens((String)history.get(history.size() - 1)); | |
1344 result.append(item.at(item.countTokens() - 1)); | |
1345 } else { | |
1346 String tail = cmd.substring(1); | |
1385 | 1347 switch (tail.charAt(0)) { |
1348 case '0': | |
1349 case '1': | |
1350 case '2': | |
1351 case '3': | |
1352 case '4': | |
1353 case '5': | |
1354 case '6': | |
1355 case '7': | |
1356 case '8': | |
1357 case '9': | |
1358 case '-': { | |
1359 int index = Integer.parseInt(tail); | |
1360 if (index < 0) { | |
1361 index = history.size() + index; | |
1362 } | |
1363 if (index > size) { | |
1364 err.println("No such history item"); | |
1365 } else { | |
1366 result.append((String)history.get(index)); | |
1367 } | |
1368 break; | |
0 | 1369 } |
1385 | 1370 default: { |
1371 for (int i = history.size() - 1; i >= 0; i--) { | |
1372 String s = (String)history.get(i); | |
1373 if (s.startsWith(tail)) { | |
1374 result.append(s); | |
1375 } | |
1376 } | |
1377 } | |
0 | 1378 } |
1379 } | |
1380 } | |
1381 if (result.length() == 0) { | |
1382 err.println("malformed history reference"); | |
1383 ln = ""; | |
1384 } else { | |
1385 if (start < ln.length()) { | |
1386 result.append(ln.substring(start)); | |
1387 } | |
1388 ln = result.toString(); | |
1389 if (!doEcho) { | |
1390 out.println(ln); | |
1391 } | |
1392 } | |
1393 } | |
1394 } | |
1395 | |
1396 if (doEcho) { | |
1397 out.println("+ " + ln); | |
1398 } | |
1399 | |
1400 PrintStream redirect = null; | |
1401 Tokens t = new Tokens(ln); | |
1402 if (t.hasMoreTokens()) { | |
1403 boolean error = false; | |
1404 history.add(ln); | |
1405 int len = t.countTokens(); | |
1406 if (len > 2) { | |
1407 String r = t.at(len - 2); | |
1408 if (r.equals(">") || r.equals(">>")) { | |
1409 boolean append = r.length() == 2; | |
1410 String file = t.at(len - 1); | |
1411 try { | |
1412 redirect = new PrintStream(new BufferedOutputStream(new FileOutputStream(file, append))); | |
1413 t.trim(2); | |
1414 } catch (Exception e) { | |
1415 out.println("Error: " + e); | |
1416 if (verboseExceptions) { | |
1417 e.printStackTrace(out); | |
1418 } | |
1419 error = true; | |
1420 } | |
1421 } | |
1422 } | |
1423 if (!error) { | |
1424 PrintStream savedout = out; | |
1425 if (redirect != null) { | |
1426 out = redirect; | |
1427 } | |
1428 try { | |
1429 executeCommand(t); | |
1430 } catch (Exception e) { | |
1431 err.println("Error: " + e); | |
1432 if (verboseExceptions) { | |
1433 e.printStackTrace(err); | |
1434 } | |
1435 } finally { | |
1436 if (redirect != null) { | |
1437 out = savedout; | |
1438 redirect.close(); | |
1439 } | |
1440 } | |
1441 } | |
1442 } | |
1443 } | |
1444 | |
1445 void executeCommand(Tokens args) { | |
1446 String cmd = args.nextToken(); | |
1447 | |
1448 Command doit = findCommand(cmd); | |
1449 | |
1450 /* | |
1451 * Check for an unknown command | |
1452 */ | |
1453 if (doit == null) { | |
1454 out.println("Unrecognized command. Try help..."); | |
1455 } else if (!debugger.isAttached() && !doit.okIfDisconnected) { | |
1456 out.println("Command not valid until the attached to a VM"); | |
1457 } else { | |
1458 try { | |
1459 doit.doit(args); | |
1460 } catch (Exception e) { | |
1461 out.println("Error: " + e); | |
1462 if (verboseExceptions) { | |
1463 e.printStackTrace(out); | |
1464 } | |
1465 } | |
1466 } | |
1467 } | |
1468 } |