/* * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// Support for showing register content on asserts/guarantees. #ifdef CAN_SHOW_REGISTERS_ON_ASSERT staticchar g_dummy; char* g_assert_poison = &g_dummy; static intx g_asserting_thread = 0; staticvoid* g_assertion_context = NULL; #endif// CAN_SHOW_REGISTERS_ON_ASSERT
// Set to suppress secondary error reporting. bool Debugging = false;
#ifndef ASSERT # ifdef _DEBUG // NOTE: don't turn the lines below into a comment -- if you're getting // a compile error here, change the settings to define ASSERT
ASSERT should be defined when _DEBUG is defined. It is not intended to be used for debugging
functions that donot slow down the system too much and thus can be left in optimized code.
On the other hand, the code should not be included in a production version. # endif // _DEBUG #endif// ASSERT
#ifdef _DEBUG # ifndef ASSERT
configuration error: ASSERT must be defined in debug version # endif // ASSERT #endif// _DEBUG
#ifdef PRODUCT # if -defined _DEBUG || -defined ASSERT
configuration error: ASSERT et al. must not be defined in PRODUCT version # endif #endif// PRODUCT
#ifdef ASSERT // This is to test that error reporting works if we assert during dynamic // initialization of the hotspot. See JDK-8214975. struct Crasher {
Crasher() { // Using getenv - no other mechanism would work yet. constchar* s = ::getenv("HOTSPOT_FATAL_ERROR_DURING_DYNAMIC_INITIALIZATION"); if (s != NULL && ::strcmp(s, "1") == 0) {
fatal("HOTSPOT_FATAL_ERROR_DURING_DYNAMIC_INITIALIZATION");
}
}
}; static Crasher g_crasher; #endif// ASSERT
// assert/guarantee/... may happen very early during VM initialization. // Don't rely on anything that is initialized by Threads::create_vm(). For // example, don't use tty. bool error_is_suppressed(constchar* file_name, int line_no) { // The following 1-element cache requires that passed-in // file names are always only constant literals. if (file_name == last_file_name && line_no == last_line_no) returntrue;
int file_name_len = (int)strlen(file_name); char separator = os::file_separator()[0]; constchar* base_name = strrchr(file_name, separator); if (base_name == NULL)
base_name = file_name;
// scan the SuppressErrorAt option constchar* cp = SuppressErrorAt; for (;;) { constchar* sfile; int sfile_len; int sline; bool noisy; while ((*cp) != '\0' && is_token_break(*cp)) cp++; if ((*cp) == '\0') break;
sfile = cp; while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':') cp++;
sfile_len = cp - sfile; if ((*cp) == ':') cp++;
sline = 0; while ((*cp) != '\0' && isdigit(*cp)) {
sline *= 10;
sline += (*cp) - '0';
cp++;
} // "file:line!" means the assert suppression is not silent
noisy = ((*cp) == '!'); while ((*cp) != '\0' && !is_token_break(*cp)) cp++; // match the line if (sline != 0) { if (sline != line_no) continue;
} // match the file if (sfile_len > 0) { constchar* look = file_name; constchar* look_max = file_name + file_name_len - sfile_len; constchar* foundp; bool match = false; while (!match
&& (foundp = strchr(look, sfile[0])) != NULL
&& foundp <= look_max) {
match = true; for (int i = 1; i < sfile_len; i++) { if (sfile[i] != foundp[i]) {
match = false; break;
}
}
look = foundp + 1;
} if (!match) continue;
} // got a match! if (noisy) {
fdStream out(defaultStream::output_fd());
out.print_raw("[error suppressed at ");
out.print_raw(base_name); char buf[16];
jio_snprintf(buf, sizeof(buf), ":%d]", line_no);
out.print_raw_cr(buf);
} else { // update 1-element cache for fast silent matches
last_file_name = file_name;
last_line_no = line_no;
} returntrue;
}
if (!VMError::is_error_reported() && !SuppressFatalErrorMessage) { // print a friendly hint:
fdStream out(defaultStream::output_fd());
out.print_raw_cr("# To suppress the following error report, specify this argument");
out.print_raw ("# after -XX: or in .hotspotrc: SuppressErrorAt=");
out.print_raw (base_name); char buf[16];
jio_snprintf(buf, sizeof(buf), ":%d", line_no);
out.print_raw_cr(buf);
} returnfalse;
}
#undef is_token_break
#else
// Place-holder for non-existent suppression check: #define error_is_suppressed(file_name, line_no) (false)
staticvoid print_error_for_unit_test(constchar* message, constchar* detail_fmt, va_list detail_args) { if (ExecutingUnitTests) { char detail_msg[256]; if (detail_fmt != NULL) { // Special handling for the sake of gtest death tests which expect the assert // message to be printed in one short line to stderr (see TEST_VM_ASSERT_MSG) and // cannot be tweaked to accept our normal assert message.
va_list detail_args_copy;
va_copy(detail_args_copy, detail_args);
jio_vsnprintf(detail_msg, sizeof(detail_msg), detail_fmt, detail_args_copy);
// The UseOSErrorReporting option in report_and_die() may allow a return // to here. If so then we'll have to figure out how to handle it.
guarantee(false, "report_and_die() should not return here");
}
void report_should_not_call(constchar* file, int line) {
report_vm_error(file, line, "ShouldNotCall()");
}
void report_should_not_reach_here(constchar* file, int line) {
report_vm_error(file, line, "ShouldNotReachHere()");
}
void report_unimplemented(constchar* file, int line) {
report_vm_error(file, line, "Unimplemented()");
}
// A number of threads may attempt to report OutOfMemoryError at around the // same time. To avoid dumping the heap or executing the data collection // commands multiple times we just do it once when the first threads reports // the error. if (Atomic::cmpxchg(&out_of_memory_reported, 0, 1) == 0) { // create heap dump before OnOutOfMemoryError commands are executed if (HeapDumpOnOutOfMemoryError) {
tty->print_cr("java.lang.OutOfMemoryError: %s", message);
HeapDumper::dump_heap_from_oome();
}
if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
VMError::report_java_out_of_memory(message);
}
if (CrashOnOutOfMemoryError) {
tty->print_cr("Aborting due to java.lang.OutOfMemoryError: %s", message);
report_fatal(OOM_JAVA_HEAP_FATAL, __FILE__, __LINE__, "OutOfMemory encountered: %s", message);
}
if (ExitOnOutOfMemoryError) {
tty->print_cr("Terminating due to java.lang.OutOfMemoryError: %s", message);
os::_exit(3); // quick exit with no cleanup hooks run
}
}
}
// ------ helper functions for debugging go here ------------
// All debug entries should be wrapped with a stack allocated // Command object. It makes sure a resource mark is set and // flushes the logfile to prevent file sharing problems.
extern"C" JNIEXPORT void nm(intptr_t p) { // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatibility)
Command c("nm");
CodeBlob* cb = CodeCache::find_blob((address)p); if (cb == NULL) {
tty->print_cr("NULL");
} else {
cb->print();
}
}
extern"C" JNIEXPORT void verify() { // try to run a verify on the entire system // note: this may not be safe if we're not at a safepoint; for debugging, // this manipulates the safepoint settings to avoid assertion failures
Command c("universe verify"); bool safe = SafepointSynchronize::is_at_safepoint(); if (!safe) {
tty->print_cr("warning: not at safepoint -- verify may fail");
SafepointSynchronize::set_is_at_safepoint();
} // Ensure Eden top is correct before verification
Universe::heap()->prepare_for_verify();
Universe::verify(); if (!safe) SafepointSynchronize::set_is_not_at_safepoint();
}
extern"C" JNIEXPORT void pp(void* p) {
Command c("pp");
FlagSetting fl(DisplayVMOutput, true); if (p == NULL) {
tty->print_cr("NULL"); return;
} if (Universe::heap()->is_in(p)) {
oop obj = cast_to_oop(p);
obj->print();
} else { // Ask NMT about this pointer. // GDB note: We will be using SafeFetch to access the supposed malloc header. If the address is // not readable, this will generate a signal. That signal will trip up the debugger: gdb will // catch the signal and disable the pp() command for further use. // In order to avoid that, switch off SIGSEGV handling with "handle SIGSEGV nostop" before // invoking pp() if (MemTracker::enabled()) { // Does it point into a known mmapped region? if (VirtualMemoryTracker::print_containing_region(p, tty)) { return;
} // Does it look like the start of a malloced block? if (MallocTracker::print_pointer_information(p, tty)) { return;
}
}
tty->print_cr(PTR_FORMAT, p2i(p));
}
}
// Prints the stack of the current Java thread
JavaThread* p = JavaThread::active();
tty->print(" for thread: ");
p->print();
tty->cr();
if (p->has_last_Java_frame()) { // If the last_Java_fp is set we are in C land and // can call the standard stack_trace function.
p->print_stack(); #ifndef PRODUCT if (Verbose) p->trace_stack();
} else {
frame f = os::current_frame();
RegisterMap reg_map(p,
RegisterMap::UpdateMap::include,
RegisterMap::ProcessFrames::include,
RegisterMap::WalkContinuation::skip);
f = f.sender(®_map);
tty->print("(guessing starting frame id=" PTR_FORMAT " based on current fp)\n", p2i(f.id()));
p->trace_stack_from(vframe::new_vframe(&f, ®_map, p)); #endif
}
}
extern"C" JNIEXPORT void pfl() { // print frame layout
Command c("pfl");
JavaThread* p = JavaThread::active();
tty->print(" for thread: ");
p->print();
tty->cr(); if (p->has_last_Java_frame()) {
p->print_frame_layout();
}
}
extern"C" JNIEXPORT void psf() { // print stack frames
{
Command c("psf");
JavaThread* p = JavaThread::active();
tty->print(" for thread: ");
p->print();
tty->cr(); if (p->has_last_Java_frame()) {
p->trace_frames();
}
}
}
// For findmethod() and findclass(): // - The patterns are matched by StringUtils::is_star_match() // - class_name_pattern matches Klass::external_name(). E.g., "java/lang/Object" or "*ang/Object" // - method_pattern may optionally the signature. E.g., "wait", "wait:()V" or "*ai*t:(*)V" // - flags must be OR'ed from ClassPrinter::Mode for findclass/findmethod // Examples (in gdb): // call findclass("java/lang/Object", 0x3) -> find j.l.Object and disasm all of its methods // call findmethod("*ang/Object*", "wait", 0xff) -> detailed disasm of all "wait" methods in j.l.Object // call findmethod("*ang/Object*", "wait:(*J*)V", 0x1) -> list all "wait" methods in j.l.Object that have a long parameter extern"C" JNIEXPORT void findclass(constchar* class_name_pattern, int flags) {
Command c("findclass");
ClassPrinter::print_flags_help(tty);
ClassPrinter::print_classes(class_name_pattern, flags, tty);
}
// check and decode a single u5 value extern"C" JNIEXPORT u4 u5decode(intptr_t addr) {
Command c("u5decode");
u1* arr = (u1*)addr;
size_t off = 0, lim = 5; if (!UNSIGNED5::check_length(arr, off, lim)) { return 0;
} return UNSIGNED5::read_uint(arr, off, lim);
}
// Sets up a Reader from addr/limit and prints count items. // A limit of zero means no set limit; stop at the first null // or after count items are printed. // A count of zero or less is converted to -1, which means // there is no limit on the count of items printed; the // printing stops when an null is printed or at limit. // See documentation for UNSIGNED5::Reader::print(count). extern"C" JNIEXPORT intptr_t u5p(intptr_t addr,
intptr_t limit, int count) {
Command c("u5p");
u1* arr = (u1*)addr; if (limit && limit < addr) limit = addr;
size_t lim = !limit ? 0 : (limit - addr);
size_t endpos = UNSIGNED5::print_count(count > 0 ? count : -1,
arr, (size_t)0, lim); return addr + endpos;
}
// int versions of all methods to avoid having to type type casts in the debugger
// // This version of pns() will not work when called from the debugger, but is // useful when called from within hotspot code. The advantages over pns() // are not having to pass in any arguments, and it will work on Windows/x64. // // WARNING: Only intended for use when debugging. Do not leave calls to // pns2() in committed source (product or debug). // extern"C" JNIEXPORT void pns2() { // print native stack
Command c("pns2"); staticchar buf[O_BUFLEN]; if (os::platform_print_native_stack(tty, NULL, buf, sizeof(buf))) { // We have printed the native stack in platform-specific code, // so nothing else to do in this case.
} else {
Thread* t = Thread::current_or_null();
frame fr = os::current_frame();
VMError::print_native_stack(tty, fr, t, false, -1, buf, sizeof(buf));
}
} #endif
// Returns true iff the address p is readable and *(intptr_t*)p != errvalue extern"C"bool dbg_is_safe(constvoid* p, intptr_t errvalue) { return p != NULL && SafeFetchN((intptr_t*)const_cast<void*>(p), errvalue) != errvalue;
}
staticvoid store_context(constvoid* context) {
memcpy(&g_stored_assertion_context, context, sizeof(ucontext_t)); #ifdefined(LINUX) && defined(PPC64) // on Linux ppc64, ucontext_t contains pointers into itself which have to be patched up // after copying the context (see comment in sys/ucontext.h):
*((void**) &g_stored_assertion_context.uc_mcontext.regs) = &(g_stored_assertion_context.uc_mcontext.gp_regs); #endif
}
bool handle_assert_poison_fault(constvoid* ucVoid, constvoid* faulting_address) { if (faulting_address == g_assert_poison) { // Disarm poison page. if (os::protect_memory((char*)g_assert_poison, os::vm_page_size(), os::MEM_PROT_RWX) == false) { #ifdef ASSERT
fprintf(stderr, "Assertion poison page cannot be unprotected - mprotect failed with %d (%s)",
errno, os::strerror(errno));
fflush(stderr); #endif returnfalse; // unprotecting memory may fail in OOM situations, as surprising as this sounds.
} // Store Context away. if (ucVoid) { const intx my_tid = os::current_thread_id(); if (Atomic::cmpxchg(&g_asserting_thread, (intx)0, my_tid) == 0) {
store_context(ucVoid);
g_assertion_context = &g_stored_assertion_context;
}
} returntrue;
} returnfalse;
} #endif// CAN_SHOW_REGISTERS_ON_ASSERT
Messung V0.5
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.