Mon, 03 Jan 2011 14:09:11 -0500
6302804: Hotspot VM dies ungraceful death when C heap is exhausted in various places.
Summary: enhance the error reporting mechanism to help user to fix the problem rather than making it look like a VM error.
Reviewed-by: kvn, kamg
1 /*
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
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 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
25 #include "precompiled.hpp"
26 #include "classfile/systemDictionary.hpp"
27 #include "code/codeCache.hpp"
28 #include "code/icBuffer.hpp"
29 #include "code/nmethod.hpp"
30 #include "code/vtableStubs.hpp"
31 #include "compiler/compileBroker.hpp"
32 #include "compiler/disassembler.hpp"
33 #include "gc_implementation/shared/markSweep.hpp"
34 #include "gc_interface/collectedHeap.hpp"
35 #include "interpreter/bytecodeHistogram.hpp"
36 #include "interpreter/interpreter.hpp"
37 #include "memory/resourceArea.hpp"
38 #include "memory/universe.hpp"
39 #include "oops/oop.inline.hpp"
40 #include "prims/privilegedStack.hpp"
41 #include "runtime/arguments.hpp"
42 #include "runtime/frame.hpp"
43 #include "runtime/java.hpp"
44 #include "runtime/sharedRuntime.hpp"
45 #include "runtime/stubCodeGenerator.hpp"
46 #include "runtime/stubRoutines.hpp"
47 #include "runtime/vframe.hpp"
48 #include "services/heapDumper.hpp"
49 #include "utilities/defaultStream.hpp"
50 #include "utilities/events.hpp"
51 #include "utilities/top.hpp"
52 #include "utilities/vmError.hpp"
53 #ifdef TARGET_OS_FAMILY_linux
54 # include "os_linux.inline.hpp"
55 # include "thread_linux.inline.hpp"
56 #endif
57 #ifdef TARGET_OS_FAMILY_solaris
58 # include "os_solaris.inline.hpp"
59 # include "thread_solaris.inline.hpp"
60 #endif
61 #ifdef TARGET_OS_FAMILY_windows
62 # include "os_windows.inline.hpp"
63 # include "thread_windows.inline.hpp"
64 #endif
66 #ifndef ASSERT
67 # ifdef _DEBUG
68 // NOTE: don't turn the lines below into a comment -- if you're getting
69 // a compile error here, change the settings to define ASSERT
70 ASSERT should be defined when _DEBUG is defined. It is not intended to be used for debugging
71 functions that do not slow down the system too much and thus can be left in optimized code.
72 On the other hand, the code should not be included in a production version.
73 # endif // _DEBUG
74 #endif // ASSERT
77 #ifdef _DEBUG
78 # ifndef ASSERT
79 configuration error: ASSERT must be defined in debug version
80 # endif // ASSERT
81 #endif // _DEBUG
84 #ifdef PRODUCT
85 # if -defined _DEBUG || -defined ASSERT
86 configuration error: ASSERT et al. must not be defined in PRODUCT version
87 # endif
88 #endif // PRODUCT
91 void warning(const char* format, ...) {
92 if (PrintWarnings) {
93 // In case error happens before init or during shutdown
94 if (tty == NULL) ostream_init();
96 tty->print("%s warning: ", VM_Version::vm_name());
97 va_list ap;
98 va_start(ap, format);
99 tty->vprint_cr(format, ap);
100 va_end(ap);
101 }
102 if (BreakAtWarning) BREAKPOINT;
103 }
105 #ifndef PRODUCT
107 #define is_token_break(ch) (isspace(ch) || (ch) == ',')
109 static const char* last_file_name = NULL;
110 static int last_line_no = -1;
112 // assert/guarantee/... may happen very early during VM initialization.
113 // Don't rely on anything that is initialized by Threads::create_vm(). For
114 // example, don't use tty.
115 bool error_is_suppressed(const char* file_name, int line_no) {
116 // The following 1-element cache requires that passed-in
117 // file names are always only constant literals.
118 if (file_name == last_file_name && line_no == last_line_no) return true;
120 int file_name_len = (int)strlen(file_name);
121 char separator = os::file_separator()[0];
122 const char* base_name = strrchr(file_name, separator);
123 if (base_name == NULL)
124 base_name = file_name;
126 // scan the SuppressErrorAt option
127 const char* cp = SuppressErrorAt;
128 for (;;) {
129 const char* sfile;
130 int sfile_len;
131 int sline;
132 bool noisy;
133 while ((*cp) != '\0' && is_token_break(*cp)) cp++;
134 if ((*cp) == '\0') break;
135 sfile = cp;
136 while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':') cp++;
137 sfile_len = cp - sfile;
138 if ((*cp) == ':') cp++;
139 sline = 0;
140 while ((*cp) != '\0' && isdigit(*cp)) {
141 sline *= 10;
142 sline += (*cp) - '0';
143 cp++;
144 }
145 // "file:line!" means the assert suppression is not silent
146 noisy = ((*cp) == '!');
147 while ((*cp) != '\0' && !is_token_break(*cp)) cp++;
148 // match the line
149 if (sline != 0) {
150 if (sline != line_no) continue;
151 }
152 // match the file
153 if (sfile_len > 0) {
154 const char* look = file_name;
155 const char* look_max = file_name + file_name_len - sfile_len;
156 const char* foundp;
157 bool match = false;
158 while (!match
159 && (foundp = strchr(look, sfile[0])) != NULL
160 && foundp <= look_max) {
161 match = true;
162 for (int i = 1; i < sfile_len; i++) {
163 if (sfile[i] != foundp[i]) {
164 match = false;
165 break;
166 }
167 }
168 look = foundp + 1;
169 }
170 if (!match) continue;
171 }
172 // got a match!
173 if (noisy) {
174 fdStream out(defaultStream::output_fd());
175 out.print_raw("[error suppressed at ");
176 out.print_raw(base_name);
177 char buf[16];
178 jio_snprintf(buf, sizeof(buf), ":%d]", line_no);
179 out.print_raw_cr(buf);
180 } else {
181 // update 1-element cache for fast silent matches
182 last_file_name = file_name;
183 last_line_no = line_no;
184 }
185 return true;
186 }
188 if (!is_error_reported()) {
189 // print a friendly hint:
190 fdStream out(defaultStream::output_fd());
191 out.print_raw_cr("# To suppress the following error report, specify this argument");
192 out.print_raw ("# after -XX: or in .hotspotrc: SuppressErrorAt=");
193 out.print_raw (base_name);
194 char buf[16];
195 jio_snprintf(buf, sizeof(buf), ":%d", line_no);
196 out.print_raw_cr(buf);
197 }
198 return false;
199 }
201 #undef is_token_break
203 #else
205 // Place-holder for non-existent suppression check:
206 #define error_is_suppressed(file_name, line_no) (false)
208 #endif //PRODUCT
210 void report_vm_error(const char* file, int line, const char* error_msg,
211 const char* detail_msg)
212 {
213 if (Debugging || error_is_suppressed(file, line)) return;
214 Thread* const thread = ThreadLocalStorage::get_thread_slow();
215 VMError err(thread, file, line, error_msg, detail_msg);
216 err.report_and_die();
217 }
219 void report_fatal(const char* file, int line, const char* message)
220 {
221 report_vm_error(file, line, "fatal error", message);
222 }
224 // Used by report_vm_out_of_memory to detect recursion.
225 static jint _exiting_out_of_mem = 0;
227 void report_vm_out_of_memory(const char* file, int line, size_t size,
228 const char* message) {
229 if (Debugging) return;
231 // We try to gather additional information for the first out of memory
232 // error only; gathering additional data might cause an allocation and a
233 // recursive out_of_memory condition.
235 const jint exiting = 1;
236 // If we succeed in changing the value, we're the first one in.
237 bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting;
239 if (first_time_here) {
240 Thread* thread = ThreadLocalStorage::get_thread_slow();
241 VMError(thread, file, line, size, message).report_and_die();
242 }
244 // Dump core and abort
245 vm_abort(true);
246 }
248 void report_should_not_call(const char* file, int line) {
249 report_vm_error(file, line, "ShouldNotCall()");
250 }
252 void report_should_not_reach_here(const char* file, int line) {
253 report_vm_error(file, line, "ShouldNotReachHere()");
254 }
256 void report_unimplemented(const char* file, int line) {
257 report_vm_error(file, line, "Unimplemented()");
258 }
260 void report_untested(const char* file, int line, const char* message) {
261 #ifndef PRODUCT
262 warning("Untested: %s in %s: %d\n", message, file, line);
263 #endif // PRODUCT
264 }
266 void report_java_out_of_memory(const char* message) {
267 static jint out_of_memory_reported = 0;
269 // A number of threads may attempt to report OutOfMemoryError at around the
270 // same time. To avoid dumping the heap or executing the data collection
271 // commands multiple times we just do it once when the first threads reports
272 // the error.
273 if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
274 // create heap dump before OnOutOfMemoryError commands are executed
275 if (HeapDumpOnOutOfMemoryError) {
276 tty->print_cr("java.lang.OutOfMemoryError: %s", message);
277 HeapDumper::dump_heap_from_oome();
278 }
280 if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
281 VMError err(message);
282 err.report_java_out_of_memory();
283 }
284 }
285 }
288 extern "C" void ps();
290 static bool error_reported = false;
292 // call this when the VM is dying--it might loosen some asserts
293 void set_error_reported() {
294 error_reported = true;
295 }
297 bool is_error_reported() {
298 return error_reported;
299 }
301 #ifndef PRODUCT
302 #include <signal.h>
304 void test_error_handler(size_t test_num)
305 {
306 if (test_num == 0) return;
308 // If asserts are disabled, use the corresponding guarantee instead.
309 size_t n = test_num;
310 NOT_DEBUG(if (n <= 2) n += 2);
312 const char* const str = "hello";
313 const size_t num = (size_t)os::vm_page_size();
315 const char* const eol = os::line_separator();
316 const char* const msg = "this message should be truncated during formatting";
318 // Keep this in sync with test/runtime/6888954/vmerrors.sh.
319 switch (n) {
320 case 1: assert(str == NULL, "expected null");
321 case 2: assert(num == 1023 && *str == 'X',
322 err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
323 case 3: guarantee(str == NULL, "expected null");
324 case 4: guarantee(num == 1023 && *str == 'X',
325 err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
326 case 5: fatal("expected null");
327 case 6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
328 case 7: fatal(err_msg("%s%s# %s%s# %s%s# %s%s# %s%s# "
329 "%s%s# %s%s# %s%s# %s%s# %s%s# "
330 "%s%s# %s%s# %s%s# %s%s# %s",
331 msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
332 msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
333 msg, eol, msg, eol, msg, eol, msg, eol, msg));
334 case 8: vm_exit_out_of_memory(num, "ChunkPool::allocate");
335 case 9: ShouldNotCallThis();
336 case 10: ShouldNotReachHere();
337 case 11: Unimplemented();
338 // This is last because it does not generate an hs_err* file on Windows.
339 case 12: os::signal_raise(SIGSEGV);
341 default: ShouldNotReachHere();
342 }
343 }
344 #endif // #ifndef PRODUCT
346 // ------ helper functions for debugging go here ------------
348 #ifndef PRODUCT
349 // All debug entries should be wrapped with a stack allocated
350 // Command object. It makes sure a resource mark is set and
351 // flushes the logfile to prevent file sharing problems.
353 class Command : public StackObj {
354 private:
355 ResourceMark rm;
356 ResetNoHandleMark rnhm;
357 HandleMark hm;
358 bool debug_save;
359 public:
360 static int level;
361 Command(const char* str) {
362 debug_save = Debugging;
363 Debugging = true;
364 if (level++ > 0) return;
365 tty->cr();
366 tty->print_cr("\"Executing %s\"", str);
367 }
369 ~Command() { tty->flush(); Debugging = debug_save; level--; }
370 };
372 int Command::level = 0;
374 extern "C" void blob(CodeBlob* cb) {
375 Command c("blob");
376 cb->print();
377 }
380 extern "C" void dump_vtable(address p) {
381 Command c("dump_vtable");
382 klassOop k = (klassOop)p;
383 instanceKlass::cast(k)->vtable()->print();
384 }
387 extern "C" void nm(intptr_t p) {
388 // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability)
389 Command c("nm");
390 CodeBlob* cb = CodeCache::find_blob((address)p);
391 if (cb == NULL) {
392 tty->print_cr("NULL");
393 } else {
394 cb->print();
395 }
396 }
399 extern "C" void disnm(intptr_t p) {
400 Command c("disnm");
401 CodeBlob* cb = CodeCache::find_blob((address) p);
402 nmethod* nm = cb->as_nmethod_or_null();
403 if (nm) {
404 nm->print();
405 Disassembler::decode(nm);
406 } else {
407 cb->print();
408 Disassembler::decode(cb);
409 }
410 }
413 extern "C" void printnm(intptr_t p) {
414 char buffer[256];
415 sprintf(buffer, "printnm: " INTPTR_FORMAT, p);
416 Command c(buffer);
417 CodeBlob* cb = CodeCache::find_blob((address) p);
418 if (cb->is_nmethod()) {
419 nmethod* nm = (nmethod*)cb;
420 nm->print_nmethod(true);
421 }
422 }
425 extern "C" void universe() {
426 Command c("universe");
427 Universe::print();
428 }
431 extern "C" void verify() {
432 // try to run a verify on the entire system
433 // note: this may not be safe if we're not at a safepoint; for debugging,
434 // this manipulates the safepoint settings to avoid assertion failures
435 Command c("universe verify");
436 bool safe = SafepointSynchronize::is_at_safepoint();
437 if (!safe) {
438 tty->print_cr("warning: not at safepoint -- verify may fail");
439 SafepointSynchronize::set_is_at_safepoint();
440 }
441 // Ensure Eden top is correct before verification
442 Universe::heap()->prepare_for_verify();
443 Universe::verify(true);
444 if (!safe) SafepointSynchronize::set_is_not_at_safepoint();
445 }
448 extern "C" void pp(void* p) {
449 Command c("pp");
450 FlagSetting fl(PrintVMMessages, true);
451 if (Universe::heap()->is_in(p)) {
452 oop obj = oop(p);
453 obj->print();
454 } else {
455 tty->print("%#p", p);
456 }
457 }
460 // pv: print vm-printable object
461 extern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); }
462 extern "C" void findpc(intptr_t x);
464 extern "C" void ps() { // print stack
465 Command c("ps");
468 // Prints the stack of the current Java thread
469 JavaThread* p = JavaThread::active();
470 tty->print(" for thread: ");
471 p->print();
472 tty->cr();
474 if (p->has_last_Java_frame()) {
475 // If the last_Java_fp is set we are in C land and
476 // can call the standard stack_trace function.
477 p->trace_stack();
478 } else {
479 frame f = os::current_frame();
480 RegisterMap reg_map(p);
481 f = f.sender(®_map);
482 tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id());
483 p->trace_stack_from(vframe::new_vframe(&f, ®_map, p));
484 pd_ps(f);
485 }
487 }
490 extern "C" void psf() { // print stack frames
491 {
492 Command c("psf");
493 JavaThread* p = JavaThread::active();
494 tty->print(" for thread: ");
495 p->print();
496 tty->cr();
497 if (p->has_last_Java_frame()) {
498 p->trace_frames();
499 }
500 }
501 }
504 extern "C" void threads() {
505 Command c("threads");
506 Threads::print(false, true);
507 }
510 extern "C" void psd() {
511 Command c("psd");
512 SystemDictionary::print();
513 }
516 extern "C" void safepoints() {
517 Command c("safepoints");
518 SafepointSynchronize::print_state();
519 }
522 extern "C" void pss() { // print all stacks
523 Command c("pss");
524 Threads::print(true, true);
525 }
528 extern "C" void debug() { // to set things up for compiler debugging
529 Command c("debug");
530 WizardMode = true;
531 PrintVMMessages = PrintCompilation = true;
532 PrintInlining = PrintAssembly = true;
533 tty->flush();
534 }
537 extern "C" void ndebug() { // undo debug()
538 Command c("ndebug");
539 PrintCompilation = false;
540 PrintInlining = PrintAssembly = false;
541 tty->flush();
542 }
545 extern "C" void flush() {
546 Command c("flush");
547 tty->flush();
548 }
551 extern "C" void events() {
552 Command c("events");
553 Events::print_last(tty, 50);
554 }
557 extern "C" void nevents(int n) {
558 Command c("events");
559 Events::print_last(tty, n);
560 }
563 // Given a heap address that was valid before the most recent GC, if
564 // the oop that used to contain it is still live, prints the new
565 // location of the oop and the address. Useful for tracking down
566 // certain kinds of naked oop and oop map bugs.
567 extern "C" void pnl(intptr_t old_heap_addr) {
568 // Print New Location of old heap address
569 Command c("pnl");
570 #ifndef VALIDATE_MARK_SWEEP
571 tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled");
572 #else
573 MarkSweep::print_new_location_of_heap_address((HeapWord*) old_heap_addr);
574 #endif
575 }
578 extern "C" methodOop findm(intptr_t pc) {
579 Command c("findm");
580 nmethod* nm = CodeCache::find_nmethod((address)pc);
581 return (nm == NULL) ? (methodOop)NULL : nm->method();
582 }
585 extern "C" nmethod* findnm(intptr_t addr) {
586 Command c("findnm");
587 return CodeCache::find_nmethod((address)addr);
588 }
590 static address same_page(address x, address y) {
591 intptr_t page_bits = -os::vm_page_size();
592 if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) {
593 return x;
594 } else if (x > y) {
595 return (address)(intptr_t(y) | ~page_bits) + 1;
596 } else {
597 return (address)(intptr_t(y) & page_bits);
598 }
599 }
601 class LookForRefInGenClosure : public OopsInGenClosure {
602 public:
603 oop target;
604 void do_oop(oop* o) {
605 if (o != NULL && *o == target) {
606 tty->print_cr(INTPTR_FORMAT, o);
607 }
608 }
609 void do_oop(narrowOop* o) { ShouldNotReachHere(); }
610 };
613 class LookForRefInObjectClosure : public ObjectClosure {
614 private:
615 LookForRefInGenClosure look_in_object;
616 public:
617 LookForRefInObjectClosure(oop target) { look_in_object.target = target; }
618 void do_object(oop obj) {
619 obj->oop_iterate(&look_in_object);
620 }
621 };
624 static void findref(intptr_t x) {
625 CollectedHeap *ch = Universe::heap();
626 LookForRefInGenClosure lookFor;
627 lookFor.target = (oop) x;
628 LookForRefInObjectClosure look_in_object((oop) x);
630 tty->print_cr("Searching heap:");
631 ch->object_iterate(&look_in_object);
633 tty->print_cr("Searching strong roots:");
634 Universe::oops_do(&lookFor, false);
635 JNIHandles::oops_do(&lookFor); // Global (strong) JNI handles
636 Threads::oops_do(&lookFor, NULL);
637 ObjectSynchronizer::oops_do(&lookFor);
638 //FlatProfiler::oops_do(&lookFor);
639 SystemDictionary::oops_do(&lookFor);
641 tty->print_cr("Searching code cache:");
642 CodeCache::oops_do(&lookFor);
644 tty->print_cr("Done.");
645 }
647 class FindClassObjectClosure: public ObjectClosure {
648 private:
649 const char* _target;
650 public:
651 FindClassObjectClosure(const char name[]) { _target = name; }
653 virtual void do_object(oop obj) {
654 if (obj->is_klass()) {
655 Klass* k = klassOop(obj)->klass_part();
656 if (k->name() != NULL) {
657 ResourceMark rm;
658 const char* ext = k->external_name();
659 if ( strcmp(_target, ext) == 0 ) {
660 tty->print_cr("Found " INTPTR_FORMAT, obj);
661 obj->print();
662 }
663 }
664 }
665 }
666 };
668 //
669 extern "C" void findclass(const char name[]) {
670 Command c("findclass");
671 if (name != NULL) {
672 tty->print_cr("Finding class %s -> ", name);
673 FindClassObjectClosure srch(name);
674 Universe::heap()->permanent_object_iterate(&srch);
675 }
676 }
678 // Another interface that isn't ambiguous in dbx.
679 // Can we someday rename the other find to hsfind?
680 extern "C" void hsfind(intptr_t x) {
681 Command c("hsfind");
682 os::print_location(tty, x, false);
683 }
686 extern "C" void hsfindref(intptr_t x) {
687 Command c("hsfindref");
688 findref(x);
689 }
691 extern "C" void find(intptr_t x) {
692 Command c("find");
693 os::print_location(tty, x, false);
694 }
697 extern "C" void findpc(intptr_t x) {
698 Command c("findpc");
699 os::print_location(tty, x, true);
700 }
703 // int versions of all methods to avoid having to type type casts in the debugger
705 void pp(intptr_t p) { pp((void*)p); }
706 void pp(oop p) { pp((void*)p); }
708 void help() {
709 Command c("help");
710 tty->print_cr("basic");
711 tty->print_cr(" pp(void* p) - try to make sense of p");
712 tty->print_cr(" pv(intptr_t p)- ((PrintableResourceObj*) p)->print()");
713 tty->print_cr(" ps() - print current thread stack");
714 tty->print_cr(" pss() - print all thread stacks");
715 tty->print_cr(" pm(int pc) - print methodOop given compiled PC");
716 tty->print_cr(" findm(intptr_t pc) - finds methodOop");
717 tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
719 tty->print_cr("misc.");
720 tty->print_cr(" flush() - flushes the log file");
721 tty->print_cr(" events() - dump last 50 events");
724 tty->print_cr("compiler debugging");
725 tty->print_cr(" debug() - to set things up for compiler debugging");
726 tty->print_cr(" ndebug() - undo debug");
727 }
729 #if 0
731 // BobV's command parser for debugging on windows when nothing else works.
733 enum CommandID {
734 CMDID_HELP,
735 CMDID_QUIT,
736 CMDID_HSFIND,
737 CMDID_PSS,
738 CMDID_PS,
739 CMDID_PSF,
740 CMDID_FINDM,
741 CMDID_FINDNM,
742 CMDID_PP,
743 CMDID_BPT,
744 CMDID_EXIT,
745 CMDID_VERIFY,
746 CMDID_THREADS,
747 CMDID_ILLEGAL = 99
748 };
750 struct CommandParser {
751 char *name;
752 CommandID code;
753 char *description;
754 };
756 struct CommandParser CommandList[] = {
757 (char *)"help", CMDID_HELP, " Dump this list",
758 (char *)"quit", CMDID_QUIT, " Return from this routine",
759 (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address",
760 (char *)"ps", CMDID_PS, " Print Current Thread Stack Trace",
761 (char *)"pss", CMDID_PSS, " Print All Thread Stack Trace",
762 (char *)"psf", CMDID_PSF, " Print All Stack Frames",
763 (char *)"findm", CMDID_FINDM, " Find a methodOop from a PC",
764 (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC",
765 (char *)"pp", CMDID_PP, " Find out something about a pointer",
766 (char *)"break", CMDID_BPT, " Execute a breakpoint",
767 (char *)"exitvm", CMDID_EXIT, "Exit the VM",
768 (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify",
769 (char *)"thread", CMDID_THREADS, "Dump Info on all Threads",
770 (char *)0, CMDID_ILLEGAL
771 };
774 // get_debug_command()
775 //
776 // Read a command from standard input.
777 // This is useful when you have a debugger
778 // which doesn't support calling into functions.
779 //
780 void get_debug_command()
781 {
782 ssize_t count;
783 int i,j;
784 bool gotcommand;
785 intptr_t addr;
786 char buffer[256];
787 nmethod *nm;
788 methodOop m;
790 tty->print_cr("You have entered the diagnostic command interpreter");
791 tty->print("The supported commands are:\n");
792 for ( i=0; ; i++ ) {
793 if ( CommandList[i].code == CMDID_ILLEGAL )
794 break;
795 tty->print_cr(" %s \n", CommandList[i].name );
796 }
798 while ( 1 ) {
799 gotcommand = false;
800 tty->print("Please enter a command: ");
801 count = scanf("%s", buffer) ;
802 if ( count >=0 ) {
803 for ( i=0; ; i++ ) {
804 if ( CommandList[i].code == CMDID_ILLEGAL ) {
805 if (!gotcommand) tty->print("Invalid command, please try again\n");
806 break;
807 }
808 if ( strcmp(buffer, CommandList[i].name) == 0 ) {
809 gotcommand = true;
810 switch ( CommandList[i].code ) {
811 case CMDID_PS:
812 ps();
813 break;
814 case CMDID_PSS:
815 pss();
816 break;
817 case CMDID_PSF:
818 psf();
819 break;
820 case CMDID_FINDM:
821 tty->print("Please enter the hex addr to pass to findm: ");
822 scanf("%I64X", &addr);
823 m = (methodOop)findm(addr);
824 tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m);
825 break;
826 case CMDID_FINDNM:
827 tty->print("Please enter the hex addr to pass to findnm: ");
828 scanf("%I64X", &addr);
829 nm = (nmethod*)findnm(addr);
830 tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm);
831 break;
832 case CMDID_PP:
833 tty->print("Please enter the hex addr to pass to pp: ");
834 scanf("%I64X", &addr);
835 pp((void*)addr);
836 break;
837 case CMDID_EXIT:
838 exit(0);
839 case CMDID_HELP:
840 tty->print("Here are the supported commands: ");
841 for ( j=0; ; j++ ) {
842 if ( CommandList[j].code == CMDID_ILLEGAL )
843 break;
844 tty->print_cr(" %s -- %s\n", CommandList[j].name,
845 CommandList[j].description );
846 }
847 break;
848 case CMDID_QUIT:
849 return;
850 break;
851 case CMDID_BPT:
852 BREAKPOINT;
853 break;
854 case CMDID_VERIFY:
855 verify();;
856 break;
857 case CMDID_THREADS:
858 threads();;
859 break;
860 case CMDID_HSFIND:
861 tty->print("Please enter the hex addr to pass to hsfind: ");
862 scanf("%I64X", &addr);
863 tty->print("Calling hsfind(0x%I64X)\n", addr);
864 hsfind(addr);
865 break;
866 default:
867 case CMDID_ILLEGAL:
868 break;
869 }
870 }
871 }
872 }
873 }
874 }
875 #endif
877 #endif // PRODUCT