Mercurial > hg > graal-jvmci-8
annotate agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java @ 6972:bd7a7ce2e264
6830717: replay of compilations would help with debugging
Summary: When java process crashed in compiler thread, repeat the compilation process will help finding root cause. This is done with using SA dump application class data and replay data from core dump, then use debug version of jvm to recompile the problematic java method.
Reviewed-by: kvn, twisti, sspitsyn
Contributed-by: yumin.qi@oracle.com
author | minqi |
---|---|
date | Mon, 12 Nov 2012 14:03:53 -0800 |
parents | 5a98bf7d847b |
children | 39432a1cefdd |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
2 * Copyright (c) 2005, 2012, 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; | |
6972
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
36 import sun.jvm.hotspot.types.basic.BasicTypeDataBase; |
0 | 37 import sun.jvm.hotspot.types.CIntegerType; |
38 import sun.jvm.hotspot.code.*; | |
39 import sun.jvm.hotspot.compiler.*; | |
40 import sun.jvm.hotspot.debugger.*; | |
41 import sun.jvm.hotspot.interpreter.*; | |
42 import sun.jvm.hotspot.memory.*; | |
43 import sun.jvm.hotspot.oops.*; | |
3939 | 44 import sun.jvm.hotspot.opto.*; |
45 import sun.jvm.hotspot.ci.*; | |
6782 | 46 import sun.jvm.hotspot.asm.*; |
0 | 47 import sun.jvm.hotspot.runtime.*; |
48 import sun.jvm.hotspot.utilities.*; | |
49 import sun.jvm.hotspot.utilities.soql.*; | |
50 import sun.jvm.hotspot.ui.classbrowser.*; | |
51 import sun.jvm.hotspot.ui.tree.*; | |
52 import sun.jvm.hotspot.tools.*; | |
53 import sun.jvm.hotspot.tools.ObjectHistogram; | |
54 import sun.jvm.hotspot.tools.StackTrace; | |
3939 | 55 import sun.jvm.hotspot.tools.jcore.ClassDump; |
56 import sun.jvm.hotspot.tools.jcore.ClassFilter; | |
0 | 57 |
58 public class CommandProcessor { | |
59 public abstract static class DebuggerInterface { | |
60 public abstract HotSpotAgent getAgent(); | |
61 public abstract boolean isAttached(); | |
62 public abstract void attach(String pid); | |
63 public abstract void attach(String java, String core); | |
64 public abstract void detach(); | |
65 public abstract void reattach(); | |
66 } | |
67 | |
3939 | 68 public static class BootFilter implements ClassFilter { |
69 public boolean canInclude(InstanceKlass kls) { | |
70 return kls.getClassLoader() == null; | |
71 } | |
72 } | |
73 | |
74 public static class NonBootFilter implements ClassFilter { | |
75 private HashMap emitted = new HashMap(); | |
76 public boolean canInclude(InstanceKlass kls) { | |
77 if (kls.getClassLoader() == null) return false; | |
78 if (emitted.get(kls.getName()) != null) { | |
79 // Since multiple class loaders are being shoved | |
80 // together duplicate classes are a possibilty. For | |
81 // now just ignore them. | |
82 return false; | |
83 } | |
84 emitted.put(kls.getName(), kls); | |
85 return true; | |
86 } | |
87 } | |
88 | |
0 | 89 static class Tokens { |
90 final String input; | |
91 int i; | |
92 String[] tokens; | |
93 int length; | |
94 | |
95 String[] splitWhitespace(String cmd) { | |
96 String[] t = cmd.split("\\s"); | |
97 if (t.length == 1 && t[0].length() == 0) { | |
98 return new String[0]; | |
99 } | |
100 return t; | |
101 } | |
102 | |
103 void add(String s, ArrayList t) { | |
104 if (s.length() > 0) { | |
105 t.add(s); | |
106 } | |
107 } | |
108 | |
109 Tokens(String cmd) { | |
110 input = cmd; | |
111 | |
112 // check for quoting | |
113 int quote = cmd.indexOf('"'); | |
114 ArrayList t = new ArrayList(); | |
115 if (quote != -1) { | |
116 while (cmd.length() > 0) { | |
117 if (quote != -1) { | |
118 int endquote = cmd.indexOf('"', quote + 1); | |
119 if (endquote == -1) { | |
120 throw new RuntimeException("mismatched quotes: " + input); | |
121 } | |
122 | |
123 String before = cmd.substring(0, quote).trim(); | |
124 String quoted = cmd.substring(quote + 1, endquote); | |
125 cmd = cmd.substring(endquote + 1).trim(); | |
126 if (before.length() > 0) { | |
127 String[] w = splitWhitespace(before); | |
128 for (int i = 0; i < w.length; i++) { | |
129 add(w[i], t); | |
130 } | |
131 } | |
132 add(quoted, t); | |
133 quote = cmd.indexOf('"'); | |
134 } else { | |
135 String[] w = splitWhitespace(cmd); | |
136 for (int i = 0; i < w.length; i++) { | |
137 add(w[i], t); | |
138 } | |
139 cmd = ""; | |
140 | |
141 } | |
142 } | |
143 } else { | |
144 String[] w = splitWhitespace(cmd); | |
145 for (int i = 0; i < w.length; i++) { | |
146 add(w[i], t); | |
147 } | |
148 } | |
149 tokens = (String[])t.toArray(new String[0]); | |
150 i = 0; | |
151 length = tokens.length; | |
152 | |
153 //for (int i = 0; i < tokens.length; i++) { | |
154 // System.out.println("\"" + tokens[i] + "\""); | |
155 //} | |
156 } | |
157 | |
158 String nextToken() { | |
159 return tokens[i++]; | |
160 } | |
161 boolean hasMoreTokens() { | |
162 return i < length; | |
163 } | |
164 int countTokens() { | |
165 return length - i; | |
166 } | |
167 void trim(int n) { | |
168 if (length >= n) { | |
169 length -= n; | |
170 } else { | |
171 throw new IndexOutOfBoundsException(String.valueOf(n)); | |
172 } | |
173 } | |
174 String join(String sep) { | |
175 StringBuffer result = new StringBuffer(); | |
176 for (int w = i; w < length; w++) { | |
177 result.append(tokens[w]); | |
178 if (w + 1 < length) { | |
179 result.append(sep); | |
180 } | |
181 } | |
182 return result.toString(); | |
183 } | |
184 | |
185 String at(int i) { | |
186 if (i < 0 || i >= length) { | |
187 throw new IndexOutOfBoundsException(String.valueOf(i)); | |
188 } | |
189 return tokens[i]; | |
190 } | |
191 } | |
192 | |
193 | |
194 abstract class Command { | |
195 Command(String n, String u, boolean ok) { | |
196 name = n; | |
197 usage = u; | |
198 okIfDisconnected = ok; | |
199 } | |
200 | |
201 Command(String n, boolean ok) { | |
202 name = n; | |
203 usage = n; | |
204 okIfDisconnected = ok; | |
205 } | |
206 | |
207 final String name; | |
208 final String usage; | |
209 final boolean okIfDisconnected; | |
210 abstract void doit(Tokens t); | |
211 void usage() { | |
212 out.println("Usage: " + usage); | |
213 } | |
214 | |
215 void printOopValue(Oop oop) { | |
216 if (oop != null) { | |
217 Klass k = oop.getKlass(); | |
218 Symbol s = k.getName(); | |
219 if (s != null) { | |
220 out.print("Oop for " + s.asString() + " @ "); | |
221 } else { | |
222 out.print("Oop @ "); | |
223 } | |
224 Oop.printOopAddressOn(oop, out); | |
225 } else { | |
226 out.print("null"); | |
227 } | |
228 } | |
229 | |
230 void printNode(SimpleTreeNode node) { | |
231 int count = node.getChildCount(); | |
232 for (int i = 0; i < count; i++) { | |
233 try { | |
234 SimpleTreeNode field = node.getChild(i); | |
235 if (field instanceof OopTreeNodeAdapter) { | |
236 out.print(field); | |
237 out.print(" "); | |
238 printOopValue(((OopTreeNodeAdapter)field).getOop()); | |
239 out.println(); | |
240 } else { | |
241 out.println(field); | |
242 } | |
243 } catch (Exception e) { | |
244 out.println(); | |
245 out.println("Error: " + e); | |
246 if (verboseExceptions) { | |
247 e.printStackTrace(out); | |
248 } | |
249 } | |
250 } | |
251 } | |
252 } | |
253 | |
254 void quote(String s) { | |
255 if (s.indexOf(" ") == -1) { | |
256 out.print(s); | |
257 } else { | |
258 out.print("\""); | |
259 out.print(s); | |
260 out.print("\""); | |
261 } | |
262 } | |
263 | |
264 void dumpType(Type type) { | |
265 out.print("type "); | |
266 quote(type.getName()); | |
267 out.print(" "); | |
268 if (type.getSuperclass() != null) { | |
269 quote(type.getSuperclass().getName()); | |
270 out.print(" "); | |
271 } else { | |
272 out.print("null "); | |
273 } | |
274 out.print(type.isOopType()); | |
275 out.print(" "); | |
276 if (type.isCIntegerType()) { | |
277 out.print("true "); | |
278 out.print(((CIntegerType)type).isUnsigned()); | |
279 out.print(" "); | |
280 } else { | |
281 out.print("false false "); | |
282 } | |
283 out.print(type.getSize()); | |
284 out.println(); | |
285 } | |
286 | |
287 void dumpFields(Type type) { | |
3939 | 288 dumpFields(type, true); |
289 } | |
290 | |
291 void dumpFields(Type type, boolean allowStatic) { | |
0 | 292 Iterator i = type.getFields(); |
293 while (i.hasNext()) { | |
294 Field f = (Field) i.next(); | |
3939 | 295 if (!allowStatic && f.isStatic()) continue; |
0 | 296 out.print("field "); |
297 quote(type.getName()); | |
298 out.print(" "); | |
299 out.print(f.getName()); | |
300 out.print(" "); | |
301 quote(f.getType().getName()); | |
302 out.print(" "); | |
303 out.print(f.isStatic()); | |
304 out.print(" "); | |
305 if (f.isStatic()) { | |
306 out.print("0 "); | |
307 out.print(f.getStaticFieldAddress()); | |
308 } else { | |
309 out.print(f.getOffset()); | |
310 out.print(" 0x0"); | |
311 } | |
312 out.println(); | |
313 } | |
314 } | |
315 | |
316 | |
317 Address lookup(String symbol) { | |
318 if (symbol.indexOf("::") != -1) { | |
319 String[] parts = symbol.split("::"); | |
320 StringBuffer mangled = new StringBuffer("__1c"); | |
321 for (int i = 0; i < parts.length; i++) { | |
322 int len = parts[i].length(); | |
323 if (len >= 26) { | |
324 mangled.append((char)('a' + (len / 26))); | |
325 len = len % 26; | |
326 } | |
327 mangled.append((char)('A' + len)); | |
328 mangled.append(parts[i]); | |
329 } | |
330 mangled.append("_"); | |
331 symbol = mangled.toString(); | |
332 } | |
333 return VM.getVM().getDebugger().lookup(null, symbol); | |
334 } | |
335 | |
336 Address parseAddress(String addr) { | |
337 return VM.getVM().getDebugger().parseAddress(addr); | |
338 } | |
339 | |
340 private final Command[] commandList = { | |
341 new Command("reattach", true) { | |
342 public void doit(Tokens t) { | |
343 int tokens = t.countTokens(); | |
344 if (tokens != 0) { | |
345 usage(); | |
346 return; | |
347 } | |
348 preAttach(); | |
349 debugger.reattach(); | |
350 postAttach(); | |
351 } | |
352 }, | |
353 new Command("attach", "attach pid | exec core", true) { | |
354 public void doit(Tokens t) { | |
355 int tokens = t.countTokens(); | |
356 if (tokens == 1) { | |
357 preAttach(); | |
358 debugger.attach(t.nextToken()); | |
359 postAttach(); | |
360 } else if (tokens == 2) { | |
361 preAttach(); | |
362 debugger.attach(t.nextToken(), t.nextToken()); | |
363 postAttach(); | |
364 } else { | |
365 usage(); | |
366 } | |
367 } | |
368 }, | |
369 new Command("detach", false) { | |
370 public void doit(Tokens t) { | |
371 if (t.countTokens() != 0) { | |
372 usage(); | |
373 } else { | |
374 debugger.detach(); | |
375 } | |
376 } | |
377 }, | |
378 new Command("examine", "examine [ address/count ] | [ address,address]", false) { | |
379 Pattern args1 = Pattern.compile("^(0x[0-9a-f]+)(/([0-9]*)([a-z]*))?$"); | |
380 Pattern args2 = Pattern.compile("^(0x[0-9a-f]+),(0x[0-9a-f]+)(/[a-z]*)?$"); | |
381 | |
382 String fill(Address a, int width) { | |
383 String s = "0x0"; | |
384 if (a != null) { | |
385 s = a.toString(); | |
386 } | |
387 if (s.length() != width) { | |
388 return s.substring(0, 2) + "000000000000000000000".substring(0, width - s.length()) + s.substring(2); | |
389 } | |
390 return s; | |
391 } | |
392 | |
393 public void doit(Tokens t) { | |
394 if (t.countTokens() != 1) { | |
395 usage(); | |
396 } else { | |
397 String arg = t.nextToken(); | |
398 Matcher m1 = args1.matcher(arg); | |
399 Matcher m2 = args2.matcher(arg); | |
400 Address start = null; | |
401 Address end = null; | |
402 String format = ""; | |
403 int formatSize = (int)VM.getVM().getAddressSize(); | |
404 | |
405 if (m1.matches()) { | |
406 start = VM.getVM().getDebugger().parseAddress(m1.group(1)); | |
407 int count = 1; | |
408 if (m1.group(2) != null) { | |
409 count = Integer.parseInt(m1.group(3)); | |
410 } | |
411 end = start.addOffsetTo(count * formatSize); | |
412 } else if (m2.matches()) { | |
413 start = VM.getVM().getDebugger().parseAddress(m2.group(1)); | |
414 end = VM.getVM().getDebugger().parseAddress(m2.group(2)); | |
415 } else { | |
416 usage(); | |
417 return; | |
418 } | |
419 int line = 80; | |
420 int formatWidth = formatSize * 8 / 4 + 2; | |
421 | |
422 out.print(fill(start, formatWidth)); | |
423 out.print(": "); | |
424 int width = line - formatWidth - 2; | |
425 | |
426 boolean needsPrintln = true; | |
427 while (start != null && start.lessThan(end)) { | |
428 Address val = start.getAddressAt(0); | |
429 out.print(fill(val, formatWidth)); | |
430 needsPrintln = true; | |
431 width -= formatWidth; | |
432 start = start.addOffsetTo(formatSize); | |
433 if (width <= formatWidth) { | |
434 out.println(); | |
435 needsPrintln = false; | |
436 if (start.lessThan(end)) { | |
437 out.print(fill(start, formatWidth)); | |
438 out.print(": "); | |
439 width = line - formatWidth - 2; | |
440 } | |
441 } else { | |
442 out.print(" "); | |
443 width -= 1; | |
444 } | |
445 } | |
446 if (needsPrintln) { | |
447 out.println(); | |
448 } | |
449 } | |
450 } | |
451 }, | |
6972
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
452 new Command("dumpreplaydata", "dumpreplaydata { <address > | -a | <thread_id> }", false) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
453 // This is used to dump replay data from ciInstanceKlass, ciMethodData etc |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
454 // default file name is replay.txt, also if java crashes in compiler |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
455 // thread, this file will be dumped in error processing. |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
456 public void doit(Tokens t) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
457 if (t.countTokens() != 1) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
458 usage(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
459 return; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
460 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
461 String name = t.nextToken(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
462 Address a = null; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
463 try { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
464 a = VM.getVM().getDebugger().parseAddress(name); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
465 } catch (NumberFormatException e) { } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
466 if (a != null) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
467 // only nmethod, Method, MethodData and InstanceKlass needed to |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
468 // dump replay data |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
469 |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
470 CodeBlob cb = VM.getVM().getCodeCache().findBlob(a); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
471 if (cb != null && (cb instanceof NMethod)) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
472 ((NMethod)cb).dumpReplayData(out); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
473 return; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
474 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
475 // assume it is Metadata |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
476 Metadata meta = Metadata.instantiateWrapperFor(a); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
477 if (meta != null) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
478 meta.dumpReplayData(out); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
479 } else { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
480 usage(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
481 return; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
482 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
483 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
484 // Not an address |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
485 boolean all = name.equals("-a"); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
486 Threads threads = VM.getVM().getThreads(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
487 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
488 ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
489 thread.printThreadIDOn(new PrintStream(bos)); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
490 if (all || bos.toString().equals(name)) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
491 if (thread instanceof CompilerThread) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
492 CompilerThread ct = (CompilerThread)thread; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
493 ciEnv env = ct.env(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
494 if (env != null) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
495 env.dumpReplayData(out); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
496 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
497 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
498 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
499 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
500 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
501 }, |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
502 new Command("buildreplayjars", "buildreplayjars [ all | app | boot ] | [ prefix ]", false) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
503 // This is used to dump jar files of all the classes |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
504 // loaded in the core. Everything on the bootclasspath |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
505 // will go in boot.jar and everything else will go in |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
506 // app.jar. Then the classes can be loaded by the replay |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
507 // jvm using -Xbootclasspath/p:boot.jar -cp app.jar. boot.jar usually |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
508 // not needed, unless changed by jvmti. |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
509 public void doit(Tokens t) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
510 int tcount = t.countTokens(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
511 if (tcount > 2) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
512 usage(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
513 return; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
514 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
515 try { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
516 String prefix = ""; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
517 String option = "all"; // default |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
518 switch(tcount) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
519 case 0: |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
520 break; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
521 case 1: |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
522 option = t.nextToken(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
523 if (!option.equalsIgnoreCase("all") && !option.equalsIgnoreCase("app") && |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
524 !option.equalsIgnoreCase("root")) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
525 prefix = option; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
526 option = "all"; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
527 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
528 break; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
529 case 2: |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
530 option = t.nextToken(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
531 prefix = t.nextToken(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
532 break; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
533 default: |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
534 usage(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
535 return; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
536 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
537 if (!option.equalsIgnoreCase("all") && !option.equalsIgnoreCase("app") && |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
538 !option.equalsIgnoreCase("boot")) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
539 usage(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
540 return; |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
541 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
542 ClassDump cd = new ClassDump(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
543 if (option.equalsIgnoreCase("all") || option.equalsIgnoreCase("boot")) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
544 cd.setClassFilter(new BootFilter()); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
545 cd.setJarOutput(prefix + "boot.jar"); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
546 cd.run(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
547 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
548 if (option.equalsIgnoreCase("all") || option.equalsIgnoreCase("app")) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
549 cd.setClassFilter(new NonBootFilter()); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
550 cd.setJarOutput(prefix + "app.jar"); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
551 cd.run(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
552 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
553 } catch (IOException ioe) { |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
554 ioe.printStackTrace(); |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
555 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
556 } |
bd7a7ce2e264
6830717: replay of compilations would help with debugging
minqi
parents:
6782
diff
changeset
|
557 }, |
0 | 558 new Command("findpc", "findpc address", false) { |
559 public void doit(Tokens t) { | |
560 if (t.countTokens() != 1) { | |
561 usage(); | |
562 } else { | |
563 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
564 PointerLocation loc = PointerFinder.find(a); | |
565 loc.printOn(out); | |
566 } | |
567 } | |
568 }, | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
569 new Command("symbol", "symbol address", false) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
570 public void doit(Tokens t) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
571 if (t.countTokens() != 1) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
572 usage(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
573 } else { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
574 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
575 Symbol.create(a).printValueOn(out); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
576 out.println(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
577 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
578 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
579 }, |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
580 new Command("symboltable", "symboltable name", false) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
581 public void doit(Tokens t) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
582 if (t.countTokens() != 1) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
583 usage(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
584 } else { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
585 out.println(SymbolTable.getTheTable().probe(t.nextToken())); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
586 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
587 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
588 }, |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
589 new Command("symboldump", "symboldump", false) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
590 public void doit(Tokens t) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
591 SymbolTable.getTheTable().symbolsDo(new SymbolTable.SymbolVisitor() { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
592 public void visit(Symbol sym) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
593 sym.printValueOn(out); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
594 out.println(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
595 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
596 }); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
597 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
598 }, |
3939 | 599 new Command("flags", "flags [ flag | -nd ]", false) { |
0 | 600 public void doit(Tokens t) { |
601 int tokens = t.countTokens(); | |
602 if (tokens != 0 && tokens != 1) { | |
603 usage(); | |
604 } else { | |
605 String name = tokens > 0 ? t.nextToken() : null; | |
3939 | 606 boolean nonDefault = false; |
607 if (name != null && name.equals("-nd")) { | |
608 name = null; | |
609 nonDefault = true; | |
610 } | |
0 | 611 |
612 VM.Flag[] flags = VM.getVM().getCommandLineFlags(); | |
613 if (flags == null) { | |
614 out.println("Command Flag info not available (use 1.4.1_03 or later)!"); | |
615 } else { | |
616 boolean printed = false; | |
617 for (int f = 0; f < flags.length; f++) { | |
618 VM.Flag flag = flags[f]; | |
619 if (name == null || flag.getName().equals(name)) { | |
3939 | 620 |
621 if (nonDefault && flag.getOrigin() == 0) { | |
622 // only print flags which aren't their defaults | |
623 continue; | |
624 } | |
625 out.println(flag.getName() + " = " + flag.getValue() + " " + flag.getOrigin()); | |
0 | 626 printed = true; |
627 } | |
628 } | |
629 if (name != null && !printed) { | |
630 out.println("Couldn't find flag: " + name); | |
631 } | |
632 } | |
633 } | |
634 } | |
635 }, | |
636 new Command("help", "help [ command ]", true) { | |
637 public void doit(Tokens t) { | |
638 int tokens = t.countTokens(); | |
639 Command cmd = null; | |
640 if (tokens == 1) { | |
641 cmd = findCommand(t.nextToken()); | |
642 } | |
643 | |
644 if (cmd != null) { | |
645 cmd.usage(); | |
646 } else if (tokens == 0) { | |
647 out.println("Available commands:"); | |
648 Object[] keys = commands.keySet().toArray(); | |
649 Arrays.sort(keys, new Comparator() { | |
650 public int compare(Object o1, Object o2) { | |
651 return o1.toString().compareTo(o2.toString()); | |
652 } | |
653 }); | |
654 for (int i = 0; i < keys.length; i++) { | |
655 out.print(" "); | |
656 out.println(((Command)commands.get(keys[i])).usage); | |
657 } | |
658 } | |
659 } | |
660 }, | |
661 new Command("history", "history", true) { | |
662 public void doit(Tokens t) { | |
663 int tokens = t.countTokens(); | |
664 if (tokens != 0 && (tokens != 1 || !t.nextToken().equals("-h"))) { | |
665 usage(); | |
666 return; | |
667 } | |
668 boolean printIndex = tokens == 0; | |
669 for (int i = 0; i < history.size(); i++) { | |
670 if (printIndex) out.print(i + " "); | |
671 out.println(history.get(i)); | |
672 } | |
673 } | |
674 }, | |
6782 | 675 // decode raw address |
676 new Command("dis", "dis address [length]", false) { | |
677 public void doit(Tokens t) { | |
678 int tokens = t.countTokens(); | |
679 if (tokens != 1 && tokens != 2) { | |
680 usage(); | |
681 return; | |
682 } | |
683 String name = t.nextToken(); | |
684 Address addr = null; | |
685 int len = 0x10; // default length | |
686 try { | |
687 addr = VM.getVM().getDebugger().parseAddress(name); | |
688 } catch (NumberFormatException e) { | |
689 out.println(e); | |
690 return; | |
691 } | |
692 if (tokens == 2) { | |
693 try { | |
694 len = Integer.parseInt(t.nextToken()); | |
695 } catch (NumberFormatException e) { | |
696 out.println(e); | |
697 return; | |
698 } | |
699 } | |
700 HTMLGenerator generator = new HTMLGenerator(false); | |
701 out.println(generator.genHTMLForRawDisassembly(addr, len)); | |
702 } | |
703 | |
704 }, | |
705 // decode codeblob or nmethod | |
706 new Command("disassemble", "disassemble address", false) { | |
707 public void doit(Tokens t) { | |
708 int tokens = t.countTokens(); | |
709 if (tokens != 1) { | |
710 usage(); | |
711 return; | |
712 } | |
713 String name = t.nextToken(); | |
714 Address addr = null; | |
715 try { | |
716 addr = VM.getVM().getDebugger().parseAddress(name); | |
717 } catch (NumberFormatException e) { | |
718 out.println(e); | |
719 return; | |
720 } | |
721 | |
722 HTMLGenerator generator = new HTMLGenerator(false); | |
723 out.println(generator.genHTML(addr)); | |
724 } | |
725 }, | |
726 // print Java bytecode disassembly | |
727 new Command("jdis", "jdis address", false) { | |
728 public void doit(Tokens t) { | |
729 int tokens = t.countTokens(); | |
730 if (tokens != 1) { | |
731 usage(); | |
732 return; | |
733 } | |
734 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
735 Method m = (Method)Metadata.instantiateWrapperFor(a); | |
736 HTMLGenerator html = new HTMLGenerator(false); | |
737 out.println(html.genHTML(m)); | |
738 } | |
739 }, | |
1385 | 740 new Command("revptrs", "revptrs address", false) { |
741 public void doit(Tokens t) { | |
742 int tokens = t.countTokens(); | |
743 if (tokens != 1 && (tokens != 2 || !t.nextToken().equals("-c"))) { | |
744 usage(); | |
745 return; | |
746 } | |
747 boolean chase = tokens == 2; | |
748 ReversePtrs revptrs = VM.getVM().getRevPtrs(); | |
749 if (revptrs == null) { | |
750 out.println("Computing reverse pointers..."); | |
751 ReversePtrsAnalysis analysis = new ReversePtrsAnalysis(); | |
752 final boolean[] complete = new boolean[1]; | |
753 HeapProgressThunk thunk = new HeapProgressThunk() { | |
754 public void heapIterationFractionUpdate(double d) {} | |
755 public synchronized void heapIterationComplete() { | |
756 complete[0] = true; | |
757 notify(); | |
758 } | |
759 }; | |
760 analysis.setHeapProgressThunk(thunk); | |
761 analysis.run(); | |
762 while (!complete[0]) { | |
763 synchronized (thunk) { | |
764 try { | |
765 thunk.wait(); | |
766 } catch (Exception e) { | |
767 } | |
768 } | |
769 } | |
770 revptrs = VM.getVM().getRevPtrs(); | |
771 out.println("Done."); | |
772 } | |
773 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
774 if (VM.getVM().getUniverse().heap().isInReserved(a)) { | |
775 OopHandle handle = a.addOffsetToAsOopHandle(0); | |
776 Oop oop = VM.getVM().getObjectHeap().newOop(handle); | |
777 ArrayList ptrs = revptrs.get(oop); | |
778 if (ptrs == null) { | |
779 out.println("no live references to " + a); | |
780 } else { | |
781 if (chase) { | |
782 while (ptrs.size() == 1) { | |
783 LivenessPathElement e = (LivenessPathElement)ptrs.get(0); | |
784 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
785 Oop.printOopValueOn(e.getObj(), new PrintStream(bos)); | |
786 out.println(bos.toString()); | |
787 ptrs = revptrs.get(e.getObj()); | |
788 } | |
789 } else { | |
790 for (int i = 0; i < ptrs.size(); i++) { | |
791 LivenessPathElement e = (LivenessPathElement)ptrs.get(i); | |
792 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
793 Oop.printOopValueOn(e.getObj(), new PrintStream(bos)); | |
794 out.println(bos.toString()); | |
795 oop = e.getObj(); | |
796 } | |
797 } | |
798 } | |
799 } | |
800 } | |
801 }, | |
3939 | 802 new Command("printmdo", "printmdo [ -a | expression ]", false) { |
803 // Print every MDO in the heap or the one referenced by expression. | |
804 public void doit(Tokens t) { | |
805 if (t.countTokens() != 1) { | |
806 usage(); | |
807 } else { | |
808 String s = t.nextToken(); | |
809 if (s.equals("-a")) { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
810 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
811 sysDict.allClassesDo(new SystemDictionary.ClassVisitor() { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
812 public void visit(Klass k) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
813 if (k instanceof InstanceKlass) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
814 MethodArray methods = ((InstanceKlass)k).getMethods(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
815 for (int i = 0; i < methods.length(); i++) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
816 Method m = methods.at(i); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
817 MethodData mdo = m.getMethodData(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
818 if (mdo != null) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
819 out.println("MethodData " + mdo.getAddress() + " for " + |
3939 | 820 "method " + m.getMethodHolder().getName().asString() + "." + |
821 m.getName().asString() + | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
822 m.getSignature().asString() + "@" + m.getAddress()); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
823 mdo.printDataOn(out); |
3939 | 824 } |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
825 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
826 } |
3939 | 827 } |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
828 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
829 ); |
3939 | 830 } else { |
831 Address a = VM.getVM().getDebugger().parseAddress(s); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
832 MethodData mdo = (MethodData) Metadata.instantiateWrapperFor(a); |
3939 | 833 mdo.printDataOn(out); |
834 } | |
835 } | |
836 } | |
837 }, | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
838 new Command("printall", "printall", false) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
839 // Print every MDO in the heap or the one referenced by expression. |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
840 public void doit(Tokens t) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
841 if (t.countTokens() != 0) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
842 usage(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
843 } else { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
844 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
845 sysDict.allClassesDo(new SystemDictionary.ClassVisitor() { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
846 public void visit(Klass k) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
847 if (k instanceof InstanceKlass && ((InstanceKlass)k).getConstants().getCache() != null) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
848 MethodArray methods = ((InstanceKlass)k).getMethods(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
849 for (int i = 0; i < methods.length(); i++) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
850 Method m = methods.at(i); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
851 HTMLGenerator gen = new HTMLGenerator(false); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
852 out.println(gen.genHTML(m)); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
853 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
854 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
855 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
856 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
857 ); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
858 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
859 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
860 }, |
3939 | 861 new Command("dumpideal", "dumpideal { -a | id }", false) { |
862 // Do a full dump of the nodes reachabile from root in each compiler thread. | |
863 public void doit(Tokens t) { | |
864 if (t.countTokens() != 1) { | |
865 usage(); | |
866 } else { | |
867 String name = t.nextToken(); | |
868 boolean all = name.equals("-a"); | |
869 Threads threads = VM.getVM().getThreads(); | |
870 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { | |
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.root().dump(9999, out); | |
881 } else { | |
882 out.println(" not compiling"); | |
883 } | |
884 } | |
885 } | |
886 } | |
887 } | |
888 } | |
889 }, | |
890 new Command("dumpcfg", "dumpcfg { -a | id }", false) { | |
891 // Dump the PhaseCFG for every compiler thread that has one live. | |
892 public void doit(Tokens t) { | |
893 if (t.countTokens() != 1) { | |
894 usage(); | |
895 } else { | |
896 String name = t.nextToken(); | |
897 boolean all = name.equals("-a"); | |
898 Threads threads = VM.getVM().getThreads(); | |
899 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { | |
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 out.println(ct); | |
906 ciEnv env = ct.env(); | |
907 if (env != null) { | |
908 Compile c = env.compilerData(); | |
909 c.cfg().dump(out); | |
910 } | |
911 } | |
912 } | |
913 } | |
914 } | |
915 } | |
916 }, | |
917 new Command("dumpilt", "dumpilt { -a | id }", false) { | |
918 // dumps the InlineTree of a C2 compile | |
919 public void doit(Tokens t) { | |
920 if (t.countTokens() != 1) { | |
921 usage(); | |
922 } else { | |
923 String name = t.nextToken(); | |
924 boolean all = name.equals("-a"); | |
925 Threads threads = VM.getVM().getThreads(); | |
926 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { | |
927 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
928 thread.printThreadIDOn(new PrintStream(bos)); | |
929 if (all || bos.toString().equals(name)) { | |
930 if (thread instanceof CompilerThread) { | |
931 CompilerThread ct = (CompilerThread)thread; | |
932 ciEnv env = ct.env(); | |
933 if (env != null) { | |
934 Compile c = env.compilerData(); | |
935 InlineTree ilt = c.ilt(); | |
936 if (ilt != null) { | |
937 ilt.print(out); | |
938 } | |
939 } | |
940 } | |
941 } | |
942 } | |
943 } | |
944 } | |
945 }, | |
946 new Command("vmstructsdump", "vmstructsdump", false) { | |
947 public void doit(Tokens t) { | |
948 if (t.countTokens() != 0) { | |
949 usage(); | |
950 return; | |
951 } | |
952 | |
953 // Dump a copy of the type database in a form that can | |
954 // be read back. | |
955 Iterator i = agent.getTypeDataBase().getTypes(); | |
956 // Make sure the types are emitted in an order than can be read back in | |
957 HashSet emitted = new HashSet(); | |
958 Stack pending = new Stack(); | |
959 while (i.hasNext()) { | |
960 Type n = (Type)i.next(); | |
961 if (emitted.contains(n.getName())) { | |
962 continue; | |
963 } | |
964 | |
965 while (n != null && !emitted.contains(n.getName())) { | |
966 pending.push(n); | |
967 n = n.getSuperclass(); | |
968 } | |
969 while (!pending.empty()) { | |
970 n = (Type)pending.pop(); | |
971 dumpType(n); | |
972 emitted.add(n.getName()); | |
973 } | |
974 } | |
975 i = agent.getTypeDataBase().getTypes(); | |
976 while (i.hasNext()) { | |
977 dumpFields((Type)i.next(), false); | |
978 } | |
979 } | |
980 }, | |
981 | |
0 | 982 new Command("inspect", "inspect expression", false) { |
983 public void doit(Tokens t) { | |
984 if (t.countTokens() != 1) { | |
985 usage(); | |
986 } else { | |
987 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
988 SimpleTreeNode node = null; | |
989 if (VM.getVM().getUniverse().heap().isInReserved(a)) { | |
990 OopHandle handle = a.addOffsetToAsOopHandle(0); | |
991 Oop oop = VM.getVM().getObjectHeap().newOop(handle); | |
992 node = new OopTreeNodeAdapter(oop, null); | |
993 | |
994 out.println("instance of " + node.getValue() + " @ " + a + | |
995 " (size = " + oop.getObjectSize() + ")"); | |
996 } else if (VM.getVM().getCodeCache().contains(a)) { | |
997 CodeBlob blob = VM.getVM().getCodeCache().findBlobUnsafe(a); | |
998 a = blob.headerBegin(); | |
999 } | |
1000 if (node == null) { | |
1001 Type type = VM.getVM().getTypeDataBase().guessTypeForAddress(a); | |
1002 if (type != null) { | |
1003 out.println("Type is " + type.getName() + " (size of " + type.getSize() + ")"); | |
1004 node = new CTypeTreeNodeAdapter(a, type, null); | |
1005 } | |
1006 } | |
1007 if (node != null) { | |
1008 printNode(node); | |
1009 } | |
1010 } | |
1011 } | |
1012 }, | |
1013 new Command("jhisto", "jhisto", false) { | |
1014 public void doit(Tokens t) { | |
1015 ObjectHistogram histo = new ObjectHistogram(); | |
1016 histo.run(out, err); | |
1017 } | |
1018 }, | |
1019 new Command("jstack", "jstack [-v]", false) { | |
1020 public void doit(Tokens t) { | |
1021 boolean verbose = false; | |
1022 if (t.countTokens() > 0 && t.nextToken().equals("-v")) { | |
1023 verbose = true; | |
1024 } | |
1025 StackTrace jstack = new StackTrace(verbose, true); | |
1026 jstack.run(out); | |
1027 } | |
1028 }, | |
1029 new Command("print", "print expression", false) { | |
1030 public void doit(Tokens t) { | |
1031 if (t.countTokens() != 1) { | |
1032 usage(); | |
1033 } else { | |
1034 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
1035 HTMLGenerator gen = new HTMLGenerator(false); | |
1036 out.println(gen.genHTML(a)); | |
1037 } | |
1038 } | |
1039 }, | |
1040 new Command("printas", "printas type expression", false) { | |
1041 public void doit(Tokens t) { | |
1042 if (t.countTokens() != 2) { | |
1043 usage(); | |
1044 } else { | |
1045 Type type = agent.getTypeDataBase().lookupType(t.nextToken()); | |
1046 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
1047 CTypeTreeNodeAdapter node = new CTypeTreeNodeAdapter(a, type, null); | |
1048 | |
1049 out.println("pointer to " + type + " @ " + a + | |
1050 " (size = " + type.getSize() + ")"); | |
1051 printNode(node); | |
1052 } | |
1053 } | |
1054 }, | |
1055 new Command("printstatics", "printstatics [ type ]", false) { | |
1056 public void doit(Tokens t) { | |
1057 if (t.countTokens() > 1) { | |
1058 usage(); | |
1059 } else { | |
1060 if (t.countTokens() == 0) { | |
1061 out.println("All known static fields"); | |
1062 printNode(new CTypeTreeNodeAdapter(agent.getTypeDataBase().getTypes())); | |
1063 } else { | |
1064 Type type = agent.getTypeDataBase().lookupType(t.nextToken()); | |
1065 out.println("Static fields of " + type.getName()); | |
1066 printNode(new CTypeTreeNodeAdapter(type)); | |
1067 } | |
1068 } | |
1069 } | |
1070 }, | |
1071 new Command("pmap", "pmap", false) { | |
1072 public void doit(Tokens t) { | |
1073 PMap pmap = new PMap(); | |
1074 pmap.run(out, debugger.getAgent().getDebugger()); | |
1075 } | |
1076 }, | |
1077 new Command("pstack", "pstack [-v]", false) { | |
1078 public void doit(Tokens t) { | |
1079 boolean verbose = false; | |
1080 if (t.countTokens() > 0 && t.nextToken().equals("-v")) { | |
1081 verbose = true; | |
1082 } | |
1083 PStack pstack = new PStack(verbose, true); | |
1084 pstack.run(out, debugger.getAgent().getDebugger()); | |
1085 } | |
1086 }, | |
1087 new Command("quit", true) { | |
1088 public void doit(Tokens t) { | |
1089 if (t.countTokens() != 0) { | |
1090 usage(); | |
1091 } else { | |
1092 debugger.detach(); | |
1093 System.exit(0); | |
1094 } | |
1095 } | |
1096 }, | |
1097 new Command("echo", "echo [ true | false ]", true) { | |
1098 public void doit(Tokens t) { | |
1099 if (t.countTokens() == 0) { | |
1100 out.println("echo is " + doEcho); | |
1101 } else if (t.countTokens() == 1) { | |
1102 doEcho = Boolean.valueOf(t.nextToken()).booleanValue(); | |
1103 } else { | |
1104 usage(); | |
1105 } | |
1106 } | |
1107 }, | |
1108 new Command("versioncheck", "versioncheck [ true | false ]", true) { | |
1109 public void doit(Tokens t) { | |
1110 if (t.countTokens() == 0) { | |
1111 out.println("versioncheck is " + | |
1112 (System.getProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck") == null)); | |
1113 } else if (t.countTokens() == 1) { | |
1114 if (Boolean.valueOf(t.nextToken()).booleanValue()) { | |
1115 System.setProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck", null); | |
1116 } else { | |
1117 System.setProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck", "true"); | |
1118 } | |
1119 } else { | |
1120 usage(); | |
1121 } | |
1122 } | |
1123 }, | |
1124 new Command("scanoops", "scanoops start end [ type ]", false) { | |
1125 public void doit(Tokens t) { | |
1126 if (t.countTokens() != 2 && t.countTokens() != 3) { | |
1127 usage(); | |
1128 } else { | |
1129 long stride = VM.getVM().getAddressSize(); | |
1130 Address base = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
1131 Address end = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
1132 Klass klass = null; | |
1133 if (t.countTokens() == 1) { | |
1134 klass = SystemDictionaryHelper.findInstanceKlass(t.nextToken()); | |
1135 } | |
1136 while (base != null && base.lessThan(end)) { | |
1137 long step = stride; | |
1138 OopHandle handle = base.addOffsetToAsOopHandle(0); | |
1139 if (RobustOopDeterminator.oopLooksValid(handle)) { | |
1140 try { | |
1141 Oop oop = VM.getVM().getObjectHeap().newOop(handle); | |
1142 if (klass == null || oop.getKlass().isSubtypeOf(klass)) | |
1143 out.println(handle.toString() + " " + oop.getKlass().getName().asString()); | |
1144 step = oop.getObjectSize(); | |
1145 } catch (UnknownOopException ex) { | |
1146 // ok | |
1147 } catch (RuntimeException ex) { | |
1148 ex.printStackTrace(); | |
1149 } | |
1150 } | |
1151 base = base.addOffsetTo(step); | |
1152 } | |
1153 } | |
1154 } | |
1155 }, | |
3939 | 1156 new Command("intConstant", "intConstant [ name [ value ] ]", true) { |
1157 public void doit(Tokens t) { | |
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 out.println("intConstant " + name + " " + db.lookupIntConstant(name)); | |
1165 } else if (t.countTokens() == 0) { | |
1166 Iterator i = db.getIntConstants(); | |
1167 while (i.hasNext()) { | |
1168 String name = (String)i.next(); | |
1169 out.println("intConstant " + name + " " + db.lookupIntConstant(name)); | |
1170 } | |
1171 } else if (t.countTokens() == 2) { | |
1172 String name = t.nextToken(); | |
1173 Integer value = Integer.valueOf(t.nextToken()); | |
1174 db.addIntConstant(name, value); | |
1175 } | |
1176 } | |
1177 }, | |
1178 new Command("longConstant", "longConstant [ name [ value ] ]", true) { | |
1179 public void doit(Tokens t) { | |
1180 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 2) { | |
1181 usage(); | |
1182 return; | |
1183 } | |
1184 HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase(); | |
1185 if (t.countTokens() == 1) { | |
1186 out.println("longConstant " + name + " " + db.lookupLongConstant(name)); | |
1187 } else if (t.countTokens() == 0) { | |
1188 Iterator i = db.getLongConstants(); | |
1189 while (i.hasNext()) { | |
1190 String name = (String)i.next(); | |
1191 out.println("longConstant " + name + " " + db.lookupLongConstant(name)); | |
1192 } | |
1193 } else if (t.countTokens() == 2) { | |
1194 String name = t.nextToken(); | |
1195 Long value = Long.valueOf(t.nextToken()); | |
1196 db.addLongConstant(name, value); | |
1197 } | |
1198 } | |
1199 }, | |
0 | 1200 new Command("field", "field [ type [ name fieldtype isStatic offset address ] ]", true) { |
1201 public void doit(Tokens t) { | |
1202 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) { | |
1203 usage(); | |
1204 return; | |
1205 } | |
1206 if (t.countTokens() == 1) { | |
1207 Type type = agent.getTypeDataBase().lookupType(t.nextToken()); | |
1208 dumpFields(type); | |
1209 } else if (t.countTokens() == 0) { | |
1210 Iterator i = agent.getTypeDataBase().getTypes(); | |
1211 while (i.hasNext()) { | |
1212 dumpFields((Type)i.next()); | |
1213 } | |
1214 } else { | |
1215 BasicType containingType = (BasicType)agent.getTypeDataBase().lookupType(t.nextToken()); | |
1216 | |
1217 String fieldName = t.nextToken(); | |
1218 | |
1219 // The field's Type must already be in the database -- no exceptions | |
1220 Type fieldType = agent.getTypeDataBase().lookupType(t.nextToken()); | |
1221 | |
1222 boolean isStatic = Boolean.valueOf(t.nextToken()).booleanValue(); | |
1223 long offset = Long.parseLong(t.nextToken()); | |
1224 Address staticAddress = parseAddress(t.nextToken()); | |
1225 if (isStatic && staticAddress == null) { | |
1226 staticAddress = lookup(containingType.getName() + "::" + fieldName); | |
1227 } | |
1228 | |
1229 // check to see if the field already exists | |
1230 Iterator i = containingType.getFields(); | |
1231 while (i.hasNext()) { | |
1232 Field f = (Field) i.next(); | |
1233 if (f.getName().equals(fieldName)) { | |
1234 if (f.isStatic() != isStatic) { | |
1235 throw new RuntimeException("static/nonstatic mismatch: " + t.input); | |
1236 } | |
1237 if (!isStatic) { | |
1238 if (f.getOffset() != offset) { | |
1239 throw new RuntimeException("bad redefinition of field offset: " + t.input); | |
1240 } | |
1241 } else { | |
1242 if (!f.getStaticFieldAddress().equals(staticAddress)) { | |
1243 throw new RuntimeException("bad redefinition of field location: " + t.input); | |
1244 } | |
1245 } | |
1246 if (f.getType() != fieldType) { | |
1247 throw new RuntimeException("bad redefinition of field type: " + t.input); | |
1248 } | |
1249 return; | |
1250 } | |
1251 } | |
1252 | |
1253 // Create field by type | |
1254 HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase(); | |
1255 db.createField(containingType, | |
1256 fieldName, fieldType, | |
1257 isStatic, | |
1258 offset, | |
1259 staticAddress); | |
1260 | |
1261 } | |
1262 } | |
1263 | |
1264 }, | |
1265 new Command("tokenize", "tokenize ...", true) { | |
1266 public void doit(Tokens t) { | |
1267 while (t.hasMoreTokens()) { | |
1268 out.println("\"" + t.nextToken() + "\""); | |
1269 } | |
1270 } | |
1271 }, | |
1272 new Command("type", "type [ type [ name super isOop isInteger isUnsigned size ] ]", true) { | |
1273 public void doit(Tokens t) { | |
1274 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) { | |
1275 usage(); | |
1276 return; | |
1277 } | |
1278 if (t.countTokens() == 6) { | |
1279 String typeName = t.nextToken(); | |
1280 String superclassName = t.nextToken(); | |
1281 if (superclassName.equals("null")) { | |
1282 superclassName = null; | |
1283 } | |
1284 boolean isOop = Boolean.valueOf(t.nextToken()).booleanValue(); | |
1285 boolean isInteger = Boolean.valueOf(t.nextToken()).booleanValue(); | |
1286 boolean isUnsigned = Boolean.valueOf(t.nextToken()).booleanValue(); | |
1287 long size = Long.parseLong(t.nextToken()); | |
1288 | |
1289 BasicType type = null; | |
1290 try { | |
1291 type = (BasicType)agent.getTypeDataBase().lookupType(typeName); | |
1292 } catch (RuntimeException e) { | |
1293 } | |
1294 if (type != null) { | |
1295 if (type.isOopType() != isOop) { | |
1296 throw new RuntimeException("oop mismatch in type definition: " + t.input); | |
1297 } | |
1298 if (type.isCIntegerType() != isInteger) { | |
1299 throw new RuntimeException("integer type mismatch in type definition: " + t.input); | |
1300 } | |
1301 if (type.isCIntegerType() && (((CIntegerType)type).isUnsigned()) != isUnsigned) { | |
1302 throw new RuntimeException("unsigned mismatch in type definition: " + t.input); | |
1303 } | |
1304 if (type.getSuperclass() == null) { | |
1305 if (superclassName != null) { | |
1306 if (type.getSize() == -1) { | |
1307 type.setSuperclass(agent.getTypeDataBase().lookupType(superclassName)); | |
1308 } else { | |
1309 throw new RuntimeException("unexpected superclass in type definition: " + t.input); | |
1310 } | |
1311 } | |
1312 } else { | |
1313 if (superclassName == null) { | |
1314 throw new RuntimeException("missing superclass in type definition: " + t.input); | |
1315 } | |
1316 if (!type.getSuperclass().getName().equals(superclassName)) { | |
1317 throw new RuntimeException("incorrect superclass in type definition: " + t.input); | |
1318 } | |
1319 } | |
1320 if (type.getSize() != size) { | |
1321 if (type.getSize() == -1) { | |
1322 type.setSize(size); | |
1323 } | |
1324 throw new RuntimeException("size mismatch in type definition: " + t.input); | |
1325 } | |
1326 return; | |
1327 } | |
1328 | |
1329 // Create type | |
1330 HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase(); | |
1331 db.createType(typeName, superclassName, isOop, isInteger, isUnsigned, size); | |
1332 } else if (t.countTokens() == 1) { | |
1333 Type type = agent.getTypeDataBase().lookupType(t.nextToken()); | |
1334 dumpType(type); | |
1335 } else { | |
1336 Iterator i = agent.getTypeDataBase().getTypes(); | |
1385 | 1337 // Make sure the types are emitted in an order than can be read back in |
1338 HashSet emitted = new HashSet(); | |
1339 Stack pending = new Stack(); | |
0 | 1340 while (i.hasNext()) { |
1385 | 1341 Type n = (Type)i.next(); |
1342 if (emitted.contains(n.getName())) { | |
1343 continue; | |
1344 } | |
1345 | |
1346 while (n != null && !emitted.contains(n.getName())) { | |
1347 pending.push(n); | |
1348 n = n.getSuperclass(); | |
1349 } | |
1350 while (!pending.empty()) { | |
1351 n = (Type)pending.pop(); | |
1352 dumpType(n); | |
1353 emitted.add(n.getName()); | |
1354 } | |
0 | 1355 } |
1356 } | |
1357 } | |
1358 | |
1359 }, | |
1360 new Command("source", "source filename", true) { | |
1361 public void doit(Tokens t) { | |
1362 if (t.countTokens() != 1) { | |
1363 usage(); | |
1364 return; | |
1365 } | |
1366 String file = t.nextToken(); | |
1367 BufferedReader savedInput = in; | |
1368 try { | |
1369 BufferedReader input = new BufferedReader(new InputStreamReader(new FileInputStream(file))); | |
1370 in = input; | |
1371 run(false); | |
1372 } catch (Exception e) { | |
1373 out.println("Error: " + e); | |
1374 if (verboseExceptions) { | |
1375 e.printStackTrace(out); | |
1376 } | |
1377 } finally { | |
1378 in = savedInput; | |
1379 } | |
1380 | |
1381 } | |
1382 }, | |
1385 | 1383 new Command("search", "search [ heap | perm | rawheap | codecache | threads ] value", false) { |
0 | 1384 public void doit(Tokens t) { |
1385 if (t.countTokens() != 2) { | |
1386 usage(); | |
1385 | 1387 return; |
1388 } | |
1389 String type = t.nextToken(); | |
1390 final Address value = VM.getVM().getDebugger().parseAddress(t.nextToken()); | |
1391 final long stride = VM.getVM().getAddressSize(); | |
1392 if (type.equals("threads")) { | |
1393 Threads threads = VM.getVM().getThreads(); | |
1394 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { | |
1395 Address base = thread.getBaseOfStackPointer(); | |
1396 Address end = thread.getLastJavaSP(); | |
1397 if (end == null) continue; | |
1398 if (end.lessThan(base)) { | |
1399 Address tmp = base; | |
1400 base = end; | |
1401 end = tmp; | |
1402 } | |
1403 out.println("Searching " + base + " " + end); | |
1404 while (base != null && base.lessThan(end)) { | |
1405 Address val = base.getAddressAt(0); | |
1406 if (AddressOps.equal(val, value)) { | |
1407 out.println(base); | |
1408 } | |
1409 base = base.addOffsetTo(stride); | |
1410 } | |
1411 } | |
1412 } else if (type.equals("rawheap")) { | |
1413 RawHeapVisitor iterator = new RawHeapVisitor() { | |
1414 public void prologue(long used) { | |
0 | 1415 } |
1385 | 1416 |
1417 public void visitAddress(Address addr) { | |
1418 Address val = addr.getAddressAt(0); | |
0 | 1419 if (AddressOps.equal(val, value)) { |
1385 | 1420 out.println("found at " + addr); |
0 | 1421 } |
1385 | 1422 } |
1423 public void visitCompOopAddress(Address addr) { | |
1424 Address val = addr.getCompOopAddressAt(0); | |
1425 if (AddressOps.equal(val, value)) { | |
1426 out.println("found at " + addr); | |
1427 } | |
0 | 1428 } |
1385 | 1429 public void epilogue() { |
1430 } | |
1431 }; | |
1432 VM.getVM().getObjectHeap().iterateRaw(iterator); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
1433 } else if (type.equals("heap")) { |
1385 | 1434 HeapVisitor iterator = new DefaultHeapVisitor() { |
1435 public boolean doObj(Oop obj) { | |
1436 int index = 0; | |
1437 Address start = obj.getHandle(); | |
1438 long end = obj.getObjectSize(); | |
1439 while (index < end) { | |
1440 Address val = start.getAddressAt(index); | |
0 | 1441 if (AddressOps.equal(val, value)) { |
1385 | 1442 out.println("found in " + obj.getHandle()); |
1443 break; | |
0 | 1444 } |
1385 | 1445 index += 4; |
0 | 1446 } |
1385 | 1447 return false; |
1448 } | |
1449 }; | |
1450 VM.getVM().getObjectHeap().iterate(iterator); | |
1451 } else if (type.equals("codecache")) { | |
1452 CodeCacheVisitor v = new CodeCacheVisitor() { | |
1453 public void prologue(Address start, Address end) { | |
1454 } | |
1455 public void visit(CodeBlob blob) { | |
1456 boolean printed = false; | |
1457 Address base = blob.getAddress(); | |
1458 Address end = base.addOffsetTo(blob.getSize()); | |
1459 while (base != null && base.lessThan(end)) { | |
1460 Address val = base.getAddressAt(0); | |
1461 if (AddressOps.equal(val, value)) { | |
1462 if (!printed) { | |
1463 printed = true; | |
3388
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2426
diff
changeset
|
1464 try { |
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2426
diff
changeset
|
1465 blob.printOn(out); |
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2426
diff
changeset
|
1466 } catch (Exception e) { |
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2426
diff
changeset
|
1467 out.println("Exception printing blob at " + base); |
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2426
diff
changeset
|
1468 e.printStackTrace(); |
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2426
diff
changeset
|
1469 } |
0 | 1470 } |
1385 | 1471 out.println("found at " + base + "\n"); |
0 | 1472 } |
1385 | 1473 base = base.addOffsetTo(stride); |
0 | 1474 } |
1385 | 1475 } |
1476 public void epilogue() { | |
1477 } | |
0 | 1478 |
1479 | |
1385 | 1480 }; |
1481 VM.getVM().getCodeCache().iterate(v); | |
0 | 1482 |
1483 } | |
1484 } | |
1485 }, | |
1040
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1486 new Command("dumpcodecache", "dumpcodecache", false) { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1487 public void doit(Tokens t) { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1488 if (t.countTokens() != 0) { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1489 usage(); |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1490 } else { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1491 final PrintStream fout = out; |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1492 final HTMLGenerator gen = new HTMLGenerator(false); |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1493 CodeCacheVisitor v = new CodeCacheVisitor() { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1494 public void prologue(Address start, Address end) { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1495 } |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1496 public void visit(CodeBlob blob) { |
1748 | 1497 fout.println(gen.genHTML(blob.contentBegin())); |
1040
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1498 } |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1499 public void epilogue() { |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1500 } |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1501 |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1502 |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1503 }; |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1504 VM.getVM().getCodeCache().iterate(v); |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1505 } |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1506 } |
873ec3787992
6892186: SA does not dump debug info for scalar replaced objects
kvn
parents:
196
diff
changeset
|
1507 }, |
0 | 1508 new Command("where", "where { -a | id }", false) { |
1509 public void doit(Tokens t) { | |
1510 if (t.countTokens() != 1) { | |
1511 usage(); | |
1512 } else { | |
1513 String name = t.nextToken(); | |
1514 Threads threads = VM.getVM().getThreads(); | |
1515 boolean all = name.equals("-a"); | |
1516 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { | |
1517 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
1518 thread.printThreadIDOn(new PrintStream(bos)); | |
1519 if (all || bos.toString().equals(name)) { | |
1385 | 1520 out.println(bos.toString() + " = " + thread.getAddress()); |
0 | 1521 HTMLGenerator gen = new HTMLGenerator(false); |
1385 | 1522 try { |
1523 out.println(gen.genHTMLForJavaStackTrace(thread)); | |
1524 } catch (Exception e) { | |
1525 err.println("Error: " + e); | |
1526 if (verboseExceptions) { | |
1527 e.printStackTrace(err); | |
1528 } | |
1529 } | |
0 | 1530 if (!all) return; |
1531 } | |
1532 } | |
1533 if (!all) out.println("Couldn't find thread " + name); | |
1534 } | |
1535 } | |
1536 }, | |
1385 | 1537 new Command("thread", "thread { -a | id }", false) { |
1538 public void doit(Tokens t) { | |
1539 if (t.countTokens() != 1) { | |
1540 usage(); | |
1541 } else { | |
1542 String name = t.nextToken(); | |
1543 Threads threads = VM.getVM().getThreads(); | |
1544 boolean all = name.equals("-a"); | |
1545 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { | |
1546 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
1547 thread.printThreadIDOn(new PrintStream(bos)); | |
1548 if (all || bos.toString().equals(name)) { | |
1549 out.println(bos.toString() + " = " + thread.getAddress()); | |
1550 if (!all) return; | |
1551 } | |
1552 } | |
1553 out.println("Couldn't find thread " + name); | |
1554 } | |
1555 } | |
1556 }, | |
0 | 1557 |
1558 new Command("threads", false) { | |
1559 public void doit(Tokens t) { | |
1560 if (t.countTokens() != 0) { | |
1561 usage(); | |
1562 } else { | |
1563 Threads threads = VM.getVM().getThreads(); | |
1564 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { | |
1565 thread.printThreadIDOn(out); | |
1566 out.println(" " + thread.getThreadName()); | |
1567 } | |
1568 } | |
1569 } | |
1570 }, | |
1571 | |
1572 new Command("livenmethods", false) { | |
1573 public void doit(Tokens t) { | |
1574 if (t.countTokens() != 0) { | |
1575 usage(); | |
1576 } else { | |
1577 ArrayList nmethods = new ArrayList(); | |
1578 Threads threads = VM.getVM().getThreads(); | |
1579 HTMLGenerator gen = new HTMLGenerator(false); | |
1580 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { | |
1581 try { | |
1582 for (JavaVFrame vf = thread.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) { | |
1583 if (vf instanceof CompiledVFrame) { | |
1584 NMethod c = ((CompiledVFrame)vf).getCode(); | |
1585 if (!nmethods.contains(c)) { | |
1586 nmethods.add(c); | |
1587 out.println(gen.genHTML(c)); | |
1588 } | |
1589 } | |
1590 } | |
1591 } catch (Exception e) { | |
1592 e.printStackTrace(); | |
1593 } | |
1594 } | |
1595 } | |
1596 } | |
1597 }, | |
1598 new Command("universe", false) { | |
1599 public void doit(Tokens t) { | |
1600 if (t.countTokens() != 0) { | |
1601 usage(); | |
1602 } else { | |
1603 Universe u = VM.getVM().getUniverse(); | |
1604 out.println("Heap Parameters:"); | |
1605 u.heap().printOn(out); | |
1606 } | |
1607 } | |
1608 }, | |
1609 new Command("verbose", "verbose true | false", true) { | |
1610 public void doit(Tokens t) { | |
1611 if (t.countTokens() != 1) { | |
1612 usage(); | |
1613 } else { | |
1614 verboseExceptions = Boolean.valueOf(t.nextToken()).booleanValue(); | |
1615 } | |
1616 } | |
1617 }, | |
1618 new Command("assert", "assert true | false", true) { | |
1619 public void doit(Tokens t) { | |
1620 if (t.countTokens() != 1) { | |
1621 usage(); | |
1622 } else { | |
1623 Assert.ASSERTS_ENABLED = Boolean.valueOf(t.nextToken()).booleanValue(); | |
1624 } | |
1625 } | |
1626 }, | |
1627 }; | |
1628 | |
1629 private boolean verboseExceptions = false; | |
1630 private ArrayList history = new ArrayList(); | |
1631 private HashMap commands = new HashMap(); | |
1632 private boolean doEcho = false; | |
1633 | |
1634 private Command findCommand(String key) { | |
1635 return (Command)commands.get(key); | |
1636 } | |
1637 | |
1638 public void printPrompt() { | |
1639 out.print("hsdb> "); | |
1640 } | |
1641 | |
1642 private DebuggerInterface debugger; | |
1643 private HotSpotAgent agent; | |
1644 private JSJavaScriptEngine jsengine; | |
1645 private BufferedReader in; | |
1646 private PrintStream out; | |
1647 private PrintStream err; | |
1648 | |
1649 // called before debuggee attach | |
1650 private void preAttach() { | |
1651 // nothing for now.. | |
1652 } | |
1653 | |
1654 // called after debuggee attach | |
1655 private void postAttach() { | |
1656 // create JavaScript engine and start it | |
1657 jsengine = new JSJavaScriptEngine() { | |
1658 private ObjectReader reader = new ObjectReader(); | |
1659 private JSJavaFactory factory = new JSJavaFactoryImpl(); | |
1660 public ObjectReader getObjectReader() { | |
1661 return reader; | |
1662 } | |
1663 public JSJavaFactory getJSJavaFactory() { | |
1664 return factory; | |
1665 } | |
1666 protected void quit() { | |
1667 debugger.detach(); | |
1668 System.exit(0); | |
1669 } | |
1670 protected BufferedReader getInputReader() { | |
1671 return in; | |
1672 } | |
1673 protected PrintStream getOutputStream() { | |
1674 return out; | |
1675 } | |
1676 protected PrintStream getErrorStream() { | |
1677 return err; | |
1678 } | |
1679 }; | |
1680 try { | |
1681 jsengine.defineFunction(this, | |
1682 this.getClass().getMethod("registerCommand", | |
1683 new Class[] { | |
1684 String.class, String.class, String.class | |
1685 })); | |
1686 } catch (NoSuchMethodException exp) { | |
1687 // should not happen, see below...!! | |
1688 exp.printStackTrace(); | |
1689 } | |
1690 jsengine.start(); | |
1691 } | |
1692 | |
1693 public void registerCommand(String cmd, String usage, final String func) { | |
1694 commands.put(cmd, new Command(cmd, usage, false) { | |
1695 public void doit(Tokens t) { | |
1696 final int len = t.countTokens(); | |
1697 Object[] args = new Object[len]; | |
1698 for (int i = 0; i < len; i++) { | |
1699 args[i] = t.nextToken(); | |
1700 } | |
1701 jsengine.call(func, args); | |
1702 } | |
1703 }); | |
1704 } | |
1705 | |
1706 public void setOutput(PrintStream o) { | |
1707 out = o; | |
1708 } | |
1709 | |
1710 public void setErr(PrintStream e) { | |
1711 err = e; | |
1712 } | |
1713 | |
1714 public CommandProcessor(DebuggerInterface debugger, BufferedReader in, PrintStream out, PrintStream err) { | |
1715 this.debugger = debugger; | |
1716 this.agent = debugger.getAgent(); | |
1717 this.in = in; | |
1718 this.out = out; | |
1719 this.err = err; | |
1720 for (int i = 0; i < commandList.length; i++) { | |
1721 Command c = commandList[i]; | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
1722 if (commands.get(c.name) != null) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
1723 throw new InternalError(c.name + " has multiple definitions"); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1748
diff
changeset
|
1724 } |
0 | 1725 commands.put(c.name, c); |
1726 } | |
1727 if (debugger.isAttached()) { | |
1728 postAttach(); | |
1729 } | |
1730 } | |
1731 | |
1732 | |
1733 public void run(boolean prompt) { | |
1734 // Process interactive commands. | |
1735 while (true) { | |
1736 if (prompt) printPrompt(); | |
1737 String ln = null; | |
1738 try { | |
1739 ln = in.readLine(); | |
1740 } catch (IOException e) { | |
1741 } | |
1742 if (ln == null) { | |
1743 if (prompt) err.println("Input stream closed."); | |
1744 return; | |
1745 } | |
1746 | |
3939 | 1747 executeCommand(ln, prompt); |
0 | 1748 } |
1749 } | |
1750 | |
1385 | 1751 static Pattern historyPattern = Pattern.compile("((!\\*)|(!\\$)|(!!-?)|(!-?[0-9][0-9]*)|(![a-zA-Z][^ ]*))"); |
0 | 1752 |
3939 | 1753 public void executeCommand(String ln, boolean putInHistory) { |
0 | 1754 if (ln.indexOf('!') != -1) { |
1755 int size = history.size(); | |
1756 if (size == 0) { | |
1757 ln = ""; | |
1758 err.println("History is empty"); | |
1759 } else { | |
1760 StringBuffer result = new StringBuffer(); | |
1761 Matcher m = historyPattern.matcher(ln); | |
1762 int start = 0; | |
1763 while (m.find()) { | |
1764 if (m.start() > start) { | |
1765 result.append(ln.substring(start, m.start() - start)); | |
1766 } | |
1767 start = m.end(); | |
1768 | |
1769 String cmd = m.group(); | |
1770 if (cmd.equals("!!")) { | |
1771 result.append((String)history.get(history.size() - 1)); | |
1772 } else if (cmd.equals("!!-")) { | |
1773 Tokens item = new Tokens((String)history.get(history.size() - 1)); | |
1774 item.trim(1); | |
1775 result.append(item.join(" ")); | |
1776 } else if (cmd.equals("!*")) { | |
1777 Tokens item = new Tokens((String)history.get(history.size() - 1)); | |
1778 item.nextToken(); | |
1779 result.append(item.join(" ")); | |
1780 } else if (cmd.equals("!$")) { | |
1781 Tokens item = new Tokens((String)history.get(history.size() - 1)); | |
1782 result.append(item.at(item.countTokens() - 1)); | |
1783 } else { | |
1784 String tail = cmd.substring(1); | |
1385 | 1785 switch (tail.charAt(0)) { |
1786 case '0': | |
1787 case '1': | |
1788 case '2': | |
1789 case '3': | |
1790 case '4': | |
1791 case '5': | |
1792 case '6': | |
1793 case '7': | |
1794 case '8': | |
1795 case '9': | |
1796 case '-': { | |
1797 int index = Integer.parseInt(tail); | |
1798 if (index < 0) { | |
1799 index = history.size() + index; | |
1800 } | |
1801 if (index > size) { | |
1802 err.println("No such history item"); | |
1803 } else { | |
1804 result.append((String)history.get(index)); | |
1805 } | |
1806 break; | |
0 | 1807 } |
1385 | 1808 default: { |
1809 for (int i = history.size() - 1; i >= 0; i--) { | |
1810 String s = (String)history.get(i); | |
1811 if (s.startsWith(tail)) { | |
1812 result.append(s); | |
1813 } | |
1814 } | |
1815 } | |
0 | 1816 } |
1817 } | |
1818 } | |
1819 if (result.length() == 0) { | |
1820 err.println("malformed history reference"); | |
1821 ln = ""; | |
1822 } else { | |
1823 if (start < ln.length()) { | |
1824 result.append(ln.substring(start)); | |
1825 } | |
1826 ln = result.toString(); | |
1827 if (!doEcho) { | |
1828 out.println(ln); | |
1829 } | |
1830 } | |
1831 } | |
1832 } | |
1833 | |
1834 if (doEcho) { | |
1835 out.println("+ " + ln); | |
1836 } | |
1837 | |
1838 PrintStream redirect = null; | |
1839 Tokens t = new Tokens(ln); | |
1840 if (t.hasMoreTokens()) { | |
1841 boolean error = false; | |
3939 | 1842 if (putInHistory) history.add(ln); |
0 | 1843 int len = t.countTokens(); |
1844 if (len > 2) { | |
1845 String r = t.at(len - 2); | |
1846 if (r.equals(">") || r.equals(">>")) { | |
1847 boolean append = r.length() == 2; | |
1848 String file = t.at(len - 1); | |
1849 try { | |
1850 redirect = new PrintStream(new BufferedOutputStream(new FileOutputStream(file, append))); | |
1851 t.trim(2); | |
1852 } catch (Exception e) { | |
1853 out.println("Error: " + e); | |
1854 if (verboseExceptions) { | |
1855 e.printStackTrace(out); | |
1856 } | |
1857 error = true; | |
1858 } | |
1859 } | |
1860 } | |
1861 if (!error) { | |
1862 PrintStream savedout = out; | |
1863 if (redirect != null) { | |
1864 out = redirect; | |
1865 } | |
1866 try { | |
1867 executeCommand(t); | |
1868 } catch (Exception e) { | |
1869 err.println("Error: " + e); | |
1870 if (verboseExceptions) { | |
1871 e.printStackTrace(err); | |
1872 } | |
1873 } finally { | |
1874 if (redirect != null) { | |
1875 out = savedout; | |
1876 redirect.close(); | |
1877 } | |
1878 } | |
1879 } | |
1880 } | |
1881 } | |
1882 | |
1883 void executeCommand(Tokens args) { | |
1884 String cmd = args.nextToken(); | |
1885 | |
1886 Command doit = findCommand(cmd); | |
1887 | |
1888 /* | |
1889 * Check for an unknown command | |
1890 */ | |
1891 if (doit == null) { | |
1892 out.println("Unrecognized command. Try help..."); | |
1893 } else if (!debugger.isAttached() && !doit.okIfDisconnected) { | |
1894 out.println("Command not valid until the attached to a VM"); | |
1895 } else { | |
1896 try { | |
1897 doit.doit(args); | |
1898 } catch (Exception e) { | |
1899 out.println("Error: " + e); | |
1900 if (verboseExceptions) { | |
1901 e.printStackTrace(out); | |
1902 } | |
1903 } | |
1904 } | |
1905 } | |
1906 } |