void VMError::report()

in src/hotspot/share/utilities/vmError.cpp [625:1387]


void VMError::report(outputStream* st, bool _verbose) {
  // Used by reattempt step logic
  static int continuation = 0;
  const char* stop_reattempt_reason = nullptr;
# define BEGIN                                             \
  if (_current_step == 0) {                                \
    _step_did_succeed = false;                             \
    _current_step = __LINE__;                              \
    {
      // [Begin logic]

# define STEP_IF(s, cond)                                  \
    }                                                      \
    _step_did_succeed = true;                              \
  }                                                        \
  if (_current_step < __LINE__) {                          \
    _step_did_succeed = false;                             \
    _current_step = __LINE__;                              \
    _current_step_info = s;                                \
    if ((cond)) {                                          \
      record_step_start_time();                            \
      _step_did_timeout = false;
      // [Step logic]

# define STEP(s) STEP_IF(s, true)

# define REATTEMPT_STEP_IF(s, cond)                        \
    }                                                      \
    _step_did_succeed = true;                              \
  }                                                        \
  if (_current_step < __LINE__ && !_step_did_succeed) {    \
    _current_step = __LINE__;                              \
    _current_step_info = s;                                \
    const bool cond_value = (cond);                        \
    if (cond_value && !can_reattempt_step(                 \
                          stop_reattempt_reason)) {        \
      st->print_cr("[stop reattempt (%s) reason: %s]",     \
                   _current_step_info,                     \
                   stop_reattempt_reason);                 \
    } else if (cond_value) {
      // [Continue Step logic]

# define END                                               \
    }                                                      \
    _step_did_succeed = true;                              \
    clear_step_start_time();                               \
  }

  // don't allocate large buffer on stack
  static char buf[O_BUFLEN];

  // Native stack trace may get stuck. We try to handle the last pc if it
  // belongs to VM generated code.
  address lastpc = nullptr;

  BEGIN
  if (MemTracker::enabled() &&
      NmtVirtualMemory_lock != nullptr &&
      _thread != nullptr &&
      NmtVirtualMemory_lock->owned_by_self()) {
    // Manually unlock to avoid reentrancy due to mallocs in detailed mode.
    NmtVirtualMemory_lock->unlock();
  }

  STEP("printing fatal error message")
    st->print_cr("#");
    if (should_report_bug(_id)) {
      st->print_cr("# A fatal error has been detected by the Java Runtime Environment:");
    } else {
      st->print_cr("# There is insufficient memory for the Java "
                   "Runtime Environment to continue.");
    }

  // avoid the cache update for malloc/mmap errors
  if (should_report_bug(_id)) {
    os::prepare_native_symbols();
  }

#ifdef ASSERT
  // Error handler self tests
  // Meaning of codes passed through in the tests.
#define TEST_SECONDARY_CRASH 14
#define TEST_REATTEMPT_SECONDARY_CRASH 15
#define TEST_RESOURCE_MARK_CRASH 2

  // test secondary error handling. Test it twice, to test that resetting
  // error handler after a secondary crash works.
  STEP_IF("test secondary crash 1", _verbose && TestCrashInErrorHandler == TEST_SECONDARY_CRASH)
    st->print_cr("Will crash now (TestCrashInErrorHandler=%u)...",
      TestCrashInErrorHandler);
    controlled_crash(TestCrashInErrorHandler);

  STEP_IF("test secondary crash 2", _verbose && TestCrashInErrorHandler == TEST_SECONDARY_CRASH)
    st->print_cr("Will crash now (TestCrashInErrorHandler=%u)...",
      TestCrashInErrorHandler);
    controlled_crash(TestCrashInErrorHandler);

  // See corresponding test in test/runtime/ErrorHandling/ReattemptErrorTest.java
  STEP_IF("test reattempt secondary crash",
      _verbose && TestCrashInErrorHandler == TEST_REATTEMPT_SECONDARY_CRASH)
    st->print_cr("Will crash now (TestCrashInErrorHandler=%u)...",
      TestCrashInErrorHandler);
    controlled_crash(14);

  REATTEMPT_STEP_IF("test reattempt secondary crash, attempt 2",
      _verbose && TestCrashInErrorHandler == TEST_REATTEMPT_SECONDARY_CRASH)
    st->print_cr("test reattempt secondary crash. attempt 2");

  REATTEMPT_STEP_IF("test reattempt secondary crash, attempt 3",
      _verbose && TestCrashInErrorHandler == TEST_REATTEMPT_SECONDARY_CRASH)
    st->print_cr("test reattempt secondary crash. attempt 3");

  STEP_IF("test reattempt timeout",
      _verbose && TestCrashInErrorHandler == TEST_REATTEMPT_SECONDARY_CRASH)
    st->print_cr("test reattempt timeout");
    os::infinite_sleep();

  REATTEMPT_STEP_IF("test reattempt timeout, attempt 2",
      _verbose && TestCrashInErrorHandler == TEST_REATTEMPT_SECONDARY_CRASH)
    st->print_cr("test reattempt timeout, attempt 2");

  STEP_IF("test reattempt stack headroom",
      _verbose && TestCrashInErrorHandler == TEST_REATTEMPT_SECONDARY_CRASH)
    st->print_cr("test reattempt stack headroom");
    reattempt_test_hit_stack_limit(st);

  REATTEMPT_STEP_IF("test reattempt stack headroom, attempt 2",
      _verbose && TestCrashInErrorHandler == TEST_REATTEMPT_SECONDARY_CRASH)
    st->print_cr("test reattempt stack headroom, attempt 2");

  STEP_IF("test missing ResourceMark does not crash",
      _verbose && TestCrashInErrorHandler == TEST_RESOURCE_MARK_CRASH)
    stringStream message;
    message.print("This is a message with no ResourceMark");
    tty->print_cr("%s", message.as_string());

  // TestUnresponsiveErrorHandler: We want to test both step timeouts and global timeout.
  // Step to global timeout ratio is 4:1, so in order to be absolutely sure we hit the
  // global timeout, let's execute the timeout step five times.
  // See corresponding test in test/runtime/ErrorHandling/TimeoutInErrorHandlingTest.java
  STEP_IF("setup for test unresponsive error reporting step",
      _verbose && TestUnresponsiveErrorHandler)
    // We record reporting_start_time for this test here because we
    // care about the time spent executing TIMEOUT_TEST_STEP and not
    // about the time it took us to get here.
    tty->print_cr("Recording reporting_start_time for TestUnresponsiveErrorHandler.");
    record_reporting_start_time();

  #define TIMEOUT_TEST_STEP STEP_IF("test unresponsive error reporting step", \
      _verbose && TestUnresponsiveErrorHandler) \
    os::infinite_sleep();
  TIMEOUT_TEST_STEP
  TIMEOUT_TEST_STEP
  TIMEOUT_TEST_STEP
  TIMEOUT_TEST_STEP
  TIMEOUT_TEST_STEP

  STEP_IF("test safefetch in error handler", _verbose && TestSafeFetchInErrorHandler)
    // test whether it is safe to use SafeFetch32 in Crash Handler. Test twice
    // to test that resetting the signal handler works correctly.
    st->print_cr("Will test SafeFetch...");
    int* const invalid_pointer = (int*)segfault_address;
    const int x = 0x76543210;
    int i1 = SafeFetch32(invalid_pointer, x);
    int i2 = SafeFetch32(invalid_pointer, x);
    if (i1 == x && i2 == x) {
      st->print_cr("SafeFetch OK."); // Correctly deflected and returned default pattern
    } else {
      st->print_cr("??");
    }
#endif // ASSERT

  STEP("printing type of error")
    switch(static_cast<unsigned int>(_id)) {
      case OOM_MALLOC_ERROR:
      case OOM_MMAP_ERROR:
      case OOM_MPROTECT_ERROR:
        if (_size) {
          st->print("# Native memory allocation ");
          st->print((_id == (int)OOM_MALLOC_ERROR) ? "(malloc) failed to allocate " :
                    (_id == (int)OOM_MMAP_ERROR)   ? "(mmap) failed to map " :
                                                    "(mprotect) failed to protect ");
          jio_snprintf(buf, sizeof(buf), "%zu", _size);
          st->print("%s", buf);
          st->print(" bytes.");
          if (strlen(_detail_msg) > 0) {
            st->print(" Error detail: ");
            st->print("%s", _detail_msg);
          }
          st->cr();
        } else {
          if (strlen(_detail_msg) > 0) {
            st->print("# ");
            st->print_cr("%s", _detail_msg);
          }
        }
        // In error file give some solutions
        if (_verbose) {
          print_oom_reasons(st);
        } else {
          return;  // that's enough for the screen
        }
        break;
      case INTERNAL_ERROR:
      default:
        break;
    }

  STEP("printing exception/signal name")
    st->print_cr("#");
    st->print("#  ");
    // Is it an OS exception/signal?
    if (os::exception_name(_id, buf, sizeof(buf))) {
      st->print("%s", buf);
      st->print(" (0x%x)", _id);                // signal number
      st->print(" at pc=" PTR_FORMAT, p2i(_pc));
      if (_siginfo != nullptr && os::signal_sent_by_kill(_siginfo)) {
        if (get_handshake_timed_out_thread() == _thread) {
          st->print(" (sent by handshake timeout handler)");
        } else if (get_safepoint_timed_out_thread() == _thread) {
          st->print(" (sent by safepoint timeout handler)");
        } else {
          st->print(" (sent by kill)");
        }
      }
    } else {
      if (should_report_bug(_id)) {
        st->print("Internal Error");
      } else {
        st->print("Out of Memory Error");
      }
      if (_filename != nullptr && _lineno > 0) {
#ifdef PRODUCT
        // In product mode chop off pathname
        const char *file = get_filename_only();
#else
        const char *file = _filename;
#endif
        st->print(" (%s:%d)", file, _lineno);
      } else {
        st->print(" (0x%x)", _id);
      }
    }

  STEP("printing current thread and pid")
    // process id, thread id
    st->print(", pid=%d", os::current_process_id());
    st->print(", tid=%zu", os::current_thread_id());
    st->cr();

  STEP_IF("printing error message", should_report_bug(_id)) // already printed the message.
    // error message
    if (strlen(_detail_msg) > 0) {
      st->print_cr("#  %s: %s", _message ? _message : "Error", _detail_msg);
    } else if (_message) {
      st->print_cr("#  Error: %s", _message);
    }

  STEP("printing Java version string")
    report_vm_version(st, buf, sizeof(buf));

  STEP_IF("printing problematic frame", _context != nullptr)
    // Print current frame if we have a context (i.e. it's a crash)
    st->print_cr("# Problematic frame:");
    st->print("# ");
    frame fr = os::fetch_frame_from_context(_context);
    fr.print_on_error(st, buf, sizeof(buf));
    st->cr();
    st->print_cr("#");

  STEP("printing core file information")
    st->print("# ");
    if (CreateCoredumpOnCrash) {
      if (coredump_status) {
        st->print("Core dump will be written. Default location: %s", coredump_message);
      } else {
        st->print("No core dump will be written. %s", coredump_message);
      }
    } else {
      st->print("CreateCoredumpOnCrash turned off, no core file dumped");
    }
    st->cr();
    st->print_cr("#");

  JFR_ONLY(STEP("printing jfr information"))
  JFR_ONLY(Jfr::on_vm_error_report(st);)

  STEP_IF("printing bug submit message", should_submit_bug_report(_id) && _verbose)
    print_bug_submit_message(st, _thread);

  STEP_IF("printing summary", _verbose)
    st->cr();
    st->print_cr("---------------  S U M M A R Y ------------");
    st->cr();

  STEP_IF("printing VM option summary", _verbose)
    // VM options
    Arguments::print_summary_on(st);
    st->cr();

  STEP_IF("printing summary machine and OS info", _verbose)
    os::print_summary_info(st, buf, sizeof(buf));

  STEP_IF("printing date and time", _verbose)
    os::print_date_and_time(st, buf, sizeof(buf));

#ifdef ADDRESS_SANITIZER
  STEP_IF("printing ASAN error information", _verbose && Asan::had_error())
    st->cr();
    st->print_cr("------------------  A S A N ----------------");
    st->cr();
    Asan::report(st);
    st->cr();
#endif // ADDRESS_SANITIZER

    STEP_IF("printing thread", _verbose)
    st->cr();
    st->print_cr("---------------  T H R E A D  ---------------");
    st->cr();

  STEP_IF("printing current thread", _verbose)
    // current thread
    if (_thread) {
      st->print("Current thread (" PTR_FORMAT "):  ", p2i(_thread));
      _thread->print_on_error(st, buf, sizeof(buf));
      st->cr();
    } else {
      st->print_cr("Current thread is native thread");
    }
    st->cr();

  STEP_IF("printing current compile task",
      _verbose && _thread != nullptr && _thread->is_Compiler_thread())
    CompilerThread* t = (CompilerThread*)_thread;
    if (t->task()) {
        st->cr();
        st->print_cr("Current CompileTask:");
        t->task()->print_line_on_error(st, buf, sizeof(buf));
        st->cr();
    }

  STEP_IF("printing stack bounds", _verbose)
    st->print("Stack: ");

    address stack_top;
    size_t stack_size;

    if (_thread) {
      stack_top = _thread->stack_base();
      stack_size = _thread->stack_size();
    } else {
      os::current_stack_base_and_size(&stack_top, &stack_size);
    }

    address stack_bottom = stack_top - stack_size;
    st->print("[" PTR_FORMAT "," PTR_FORMAT "]", p2i(stack_bottom), p2i(stack_top));

    frame fr = _context ? os::fetch_frame_from_context(_context)
                        : os::current_frame();

    if (fr.sp()) {
      st->print(",  sp=" PTR_FORMAT, p2i(fr.sp()));
      size_t free_stack_size = pointer_delta(fr.sp(), stack_bottom, 1024);
      st->print(",  free space=%zuk", free_stack_size);
    }

    st->cr();

  STEP_IF("printing native stack (with source info)", _verbose)

    NativeStackPrinter nsp(_thread, _context, _filename != nullptr ? get_filename_only() : nullptr, _lineno);
    if (nsp.print_stack(st, buf, sizeof(buf), lastpc,
                        true /*print_source_info */, -1 /* max stack */)) {
      // We have printed the native stack in platform-specific code
      // Windows/x64 needs special handling.
      // Stack walking may get stuck. Try to find the calling code.
      if (lastpc != nullptr) {
        const char* name = find_code_name(lastpc);
        if (name != nullptr) {
          st->print_cr("The last pc belongs to %s (printed below).", name);
        }
      }
    } else {
      _print_stack_from_frame_used = true; // frame-based native stack walk done
    }

  REATTEMPT_STEP_IF("retry printing native stack (no source info)", _verbose)
    st->cr();
    st->print_cr("Retrying call stack printing without source information...");
    NativeStackPrinter nsp(_thread, _context, get_filename_only(), _lineno);
    nsp.print_stack_from_frame(st, buf, sizeof(buf),
                               false /*print_source_info */, -1 /* max stack */);
    _print_stack_from_frame_used = true;

  STEP_IF("printing Java stack", _verbose && _thread && _thread->is_Java_thread())
    if (_verbose && _thread && _thread->is_Java_thread()) {
      print_stack_trace(st, JavaThread::cast(_thread), buf, sizeof(buf));
    }

  STEP_IF("printing target Java thread stack",
      _verbose && _thread != nullptr && (_thread->is_Named_thread()))
    // printing Java thread stack trace if it is involved in GC crash
    Thread* thread = ((NamedThread *)_thread)->processed_thread();
    if (thread != nullptr && thread->is_Java_thread()) {
      JavaThread* jt = JavaThread::cast(thread);
      st->print_cr("JavaThread " PTR_FORMAT " (nid = %d) was being processed", p2i(jt), jt->osthread()->thread_id());
      print_stack_trace(st, jt, buf, sizeof(buf), true);
    }

  STEP_IF("printing siginfo", _verbose && _siginfo != nullptr)
    // signal no, signal code, address that caused the fault
    st->cr();
    os::print_siginfo(st, _siginfo);
    st->cr();

  STEP_IF("CDS archive access warning", _verbose && _siginfo != nullptr)
    // Print an explicit hint if we crashed on access to the CDS archive.
    check_failing_cds_access(st, _siginfo);
    st->cr();

#if defined(COMPILER1) || defined(COMPILER2)
  STEP_IF("printing pending compilation failure",
          _verbose && _thread != nullptr && _thread->is_Compiler_thread())
    CompilationFailureInfo::print_pending_compilation_failure(st);
  if (CompilationMemoryStatistic::enabled() && CompilationMemoryStatistic::in_oom_crash()) {
    st->cr();
    st->print_cr(">> Please see below for a detailed breakdown of compiler memory usage.");
    st->cr();
  }
#endif

  STEP_IF("printing registers", _verbose && _context != nullptr)
    // printing registers
    os::print_context(st, _context);
    st->cr();

  STEP_IF("printing register info",
      _verbose && _context != nullptr && _thread != nullptr && Universe::is_fully_initialized())
    continuation = 0;
    ResourceMark rm(_thread);
    st->print_cr("Register to memory mapping:");
    st->cr();
    os::print_register_info(st, _context, continuation);
    st->cr();

  REATTEMPT_STEP_IF("printing register info, attempt 2",
      _verbose && _context != nullptr && _thread != nullptr && Universe::is_fully_initialized())
    ResourceMark rm(_thread);
    os::print_register_info(st, _context, continuation);
    st->cr();

  REATTEMPT_STEP_IF("printing register info, attempt 3",
      _verbose && _context != nullptr && _thread != nullptr && Universe::is_fully_initialized())
    ResourceMark rm(_thread);
    os::print_register_info(st, _context, continuation);
    st->cr();

  STEP_IF("printing top of stack, instructions near pc", _verbose && _context != nullptr)
    // printing top of stack, instructions near pc
    os::print_tos_pc(st, _context);
    st->cr();

  STEP_IF("inspecting top of stack",
      _verbose && _context != nullptr && _thread != nullptr && Universe::is_fully_initialized())
    continuation = 0;
    ResourceMark rm(_thread);
    st->print_cr("Stack slot to memory mapping:");
    st->cr();
    print_stack_location(st, _context, continuation);
    st->cr();

  REATTEMPT_STEP_IF("inspecting top of stack, attempt 2",
      _verbose && _context != nullptr && _thread != nullptr && Universe::is_fully_initialized())
    ResourceMark rm(_thread);
    print_stack_location(st, _context, continuation);
    st->cr();

  REATTEMPT_STEP_IF("inspecting top of stack, attempt 3",
      _verbose && _context != nullptr && _thread != nullptr && Universe::is_fully_initialized())
    ResourceMark rm(_thread);
    print_stack_location(st, _context, continuation);
    st->cr();

  STEP_IF("printing lock stack", _verbose && _thread != nullptr && _thread->is_Java_thread());
    st->print_cr("Lock stack of current Java thread (top to bottom):");
    JavaThread::cast(_thread)->lock_stack().print_on(st);
    st->cr();

  STEP_IF("printing code blobs if possible", _verbose)
    const int printed_capacity = max_error_log_print_code;
    address printed[printed_capacity];
    printed[0] = nullptr;
    int printed_len = 0;
    // Even though ErrorLogPrintCodeLimit is ranged checked
    // during argument parsing, there's no way to prevent it
    // subsequently (i.e., after parsing) being set to a
    // value outside the range.
    int limit = MIN2(ErrorLogPrintCodeLimit, printed_capacity);
    if (limit > 0) {
      // Check if a pc was found by native stack trace above.
      if (lastpc != nullptr) {
        if (print_code(st, _thread, lastpc, true, printed, printed_capacity)) {
          printed_len++;
        }
      }

      // Scan the native stack
      if (!_print_stack_from_frame_used) {
        // Only try to print code of the crashing frame since
        // the native stack cannot be walked with next_frame.
        if (print_code(st, _thread, _pc, true, printed, printed_capacity)) {
          printed_len++;
        }
      } else {
        frame fr = _context ? os::fetch_frame_from_context(_context)
                            : os::current_frame();
        while (printed_len < limit && fr.pc() != nullptr) {
          if (print_code(st, _thread, fr.pc(), fr.pc() == _pc, printed, printed_capacity)) {
            printed_len++;
          }
          fr = frame::next_frame(fr, _thread);
        }
      }

      // Scan the Java stack
      if (_thread != nullptr && _thread->is_Java_thread()) {
        JavaThread* jt = JavaThread::cast(_thread);
        if (jt->has_last_Java_frame()) {
          for (StackFrameStream sfs(jt, true /* update */, true /* process_frames */); printed_len < limit && !sfs.is_done(); sfs.next()) {
            address pc = sfs.current()->pc();
            if (print_code(st, _thread, pc, pc == _pc, printed, printed_capacity)) {
              printed_len++;
            }
          }
        }
      }
    }

  STEP_IF("printing VM operation", _verbose && _thread != nullptr && _thread->is_VM_thread())
    VMThread* t = (VMThread*)_thread;
    VM_Operation* op = t->vm_operation();
    if (op) {
      op->print_on_error(st);
      st->cr();
      st->cr();
    }

  STEP_IF("printing registered callbacks", _verbose && _thread != nullptr);
    size_t count = 0;
    for (VMErrorCallback* callback = _thread->_vm_error_callbacks;
        callback != nullptr;
        callback = callback->_next) {
      st->print_cr("VMErrorCallback %zu:", ++count);
      callback->call(st);
      st->cr();
    }

  STEP_IF("printing process", _verbose)
    st->cr();
    st->print_cr("---------------  P R O C E S S  ---------------");
    st->cr();

  STEP_IF("printing user info", ExtensiveErrorReports && _verbose)
    os::print_user_info(st);

  STEP_IF("printing all threads", _verbose && _thread != nullptr)
    // all threads
    Threads::print_on_error(st, _thread, buf, sizeof(buf));
    st->cr();

  STEP_IF("printing VM state", _verbose)
    // Safepoint state
    st->print("VM state: ");

    if (SafepointSynchronize::is_synchronizing()) st->print("synchronizing");
    else if (SafepointSynchronize::is_at_safepoint()) st->print("at safepoint");
    else st->print("not at safepoint");

    // Also see if error occurred during initialization or shutdown
    if (!Universe::is_fully_initialized()) {
      st->print(" (not fully initialized)");
    } else if (VM_Exit::vm_exited()) {
      st->print(" (shutting down)");
    } else {
      st->print(" (normal execution)");
    }
    st->cr();
    st->cr();

  STEP_IF("printing owned locks on error", _verbose)
    // mutexes/monitors that currently have an owner
    Mutex::print_owned_locks_on_error(st);
    st->cr();

  STEP_IF("printing number of OutOfMemoryError and StackOverflow exceptions",
      _verbose && Exceptions::has_exception_counts())
    st->print_cr("OutOfMemory and StackOverflow Exception counts:");
    Exceptions::print_exception_counts_on_error(st);
    st->cr();

#ifdef _LP64
  STEP_IF("printing compressed oops mode", _verbose && UseCompressedOops)
    CompressedOops::print_mode(st);
    st->cr();

  STEP_IF("printing compressed klass pointers mode", _verbose && UseCompressedClassPointers)
    CDS_ONLY(AOTMetaspace::print_on(st);)
    Metaspace::print_compressed_class_space(st);
    CompressedKlassPointers::print_mode(st);
    st->cr();
#endif

  STEP_IF("printing heap information", _verbose)
    GCLogPrecious::print_on_error(st);

    if (Universe::heap() != nullptr) {
      st->print_cr("Heap:");
      StreamIndentor si(st, 1);
      Universe::heap()->print_heap_on(st);
      st->cr();
    }

  STEP_IF("printing GC information", _verbose)
    if (Universe::heap() != nullptr) {
      Universe::heap()->print_gc_on(st);
      st->cr();
    }

    if (Universe::is_fully_initialized()) {
      st->print_cr("Polling page: " PTR_FORMAT, p2i(SafepointMechanism::get_polling_page()));
      st->cr();
    }

  STEP_IF("printing metaspace information", _verbose && Universe::is_fully_initialized())
    st->print_cr("Metaspace:");
    MetaspaceUtils::print_on(st);
    MetaspaceUtils::print_basic_report(st, 0);

  STEP_IF("printing code cache information", _verbose && Universe::is_fully_initialized())
    // print code cache information before vm abort
    CodeCache::print_summary(st);
    st->cr();

  STEP_IF("printing ring buffers", _verbose)
    Events::print_all(st);
    st->cr();

  STEP_IF("printing dynamic libraries", _verbose)
    // dynamic libraries, or memory map
    os::print_dll_info(st);
    st->cr();

#if INCLUDE_JVMTI
  STEP_IF("printing jvmti agent info", _verbose)
    os::print_jvmti_agent_info(st);
    st->cr();
#endif

  STEP_IF("printing native decoder state", _verbose)
    Decoder::print_state_on(st);
    st->cr();

  STEP_IF("printing VM options", _verbose)
    // VM options
    Arguments::print_on(st);
    st->cr();

  STEP_IF("printing flags", _verbose)
    JVMFlag::printFlags(
      st,
      true, // with comments
      false, // no ranges
      true); // skip defaults
    st->cr();

  STEP_IF("printing warning if internal testing API used", WhiteBox::used())
    st->print_cr("Unsupported internal testing APIs have been used.");
    st->cr();

  STEP_IF("printing log configuration", _verbose)
    st->print_cr("Logging:");
    LogConfiguration::describe_current_configuration(st);
    st->cr();

  STEP_IF("printing release file content", _verbose)
    st->print_cr("Release file:");
    os::print_image_release_file(st);

  STEP_IF("printing all environment variables", _verbose)
    os::print_environment_variables(st, env_list);
    st->cr();

  STEP_IF("printing locale settings", _verbose)
    os::print_active_locale(st);
    st->cr();

  STEP_IF("printing signal handlers", _verbose)
    os::print_signal_handlers(st, buf, sizeof(buf));
    st->cr();

  STEP_IF("Native Memory Tracking", _verbose && _thread != nullptr)
    MemTracker::error_report(st);
    st->cr();

  STEP_IF("printing compiler memory info, if any", _verbose)
    CompilationMemoryStatistic::print_error_report(st);
    st->cr();

  STEP_IF("printing periodic trim state", _verbose)
    NativeHeapTrimmer::print_state(st);
    st->cr();

  STEP_IF("JNI global references", _verbose)
    st->print_cr("JNI global refs:");
    JNIHandles::print_on_unsafe(st);
    JNIHandles::print_memory_usage_on(st);

  STEP_IF("Process memory usage", _verbose)
  print_process_memory_usage(st);

  STEP_IF("OOME stack traces", _verbose)
    st->print_cr("OOME stack traces (most recent first):");
    print_oome_stacks(st);

  STEP_IF("Classloader stats", _verbose)
    st->print_cr("Classloader memory used:");
    FREE_C_HEAP_ARRAY(void*, _ballast_memory);
    _ballast_memory = nullptr;
    print_classloaders_stats(st);
    print_dup_classes(st); // do it separately in case we're low on memory

  STEP_IF("printing system", _verbose)
    st->print_cr("---------------  S Y S T E M  ---------------");
    st->cr();

  STEP_IF("printing OS information", _verbose)
    os::print_os_info(st);
    st->cr();

  STEP_IF("printing CPU info", _verbose)
    os::print_cpu_info(st, buf, sizeof(buf));
    st->cr();

  STEP_IF("printing memory info", _verbose)
    os::print_memory_info(st);
    st->cr();

  STEP_IF("printing internal vm info", _verbose)
    st->print_cr("vm_info: %s", VM_Version::internal_vm_info_string());
    st->cr();

  // print a defined marker to show that error handling finished correctly.
  STEP_IF("printing end marker", _verbose)
    st->print_cr("END.");

  END

# undef BEGIN
# undef STEP_IF
# undef STEP
# undef REATTEMPT_STEP_IF
# undef END
}