8303422: Use common functions to exit the VM for -Xshare:dump and CDS errors

Reviewed-by: iklam, coleenp, fparain
This commit is contained in:
Matias Saavedra Silva 2023-04-17 21:38:46 +00:00
parent bb1a7bb3e1
commit e3ece365ce
9 changed files with 82 additions and 66 deletions

@ -331,7 +331,7 @@ address ArchiveBuilder::reserve_buffer() {
ReservedSpace rs(buffer_size, MetaspaceShared::core_region_alignment(), os::vm_page_size());
if (!rs.is_reserved()) {
log_error(cds)("Failed to reserve " SIZE_FORMAT " bytes of output buffer.", buffer_size);
os::_exit(0);
MetaspaceShared::unrecoverable_writing_error();
}
// buffer_bottom is the lowest address of the 2 core regions (rw, ro) when
@ -381,7 +381,7 @@ address ArchiveBuilder::reserve_buffer() {
log_error(cds)("my_archive_requested_top = " INTPTR_FORMAT, p2i(my_archive_requested_top));
log_error(cds)("SharedBaseAddress (" INTPTR_FORMAT ") is too high. "
"Please rerun java -Xshare:dump with a lower value", p2i(_requested_static_archive_bottom));
os::_exit(0);
MetaspaceShared::unrecoverable_writing_error();
}
if (DumpSharedSpaces) {
@ -1269,8 +1269,8 @@ void ArchiveBuilder::report_out_of_space(const char* name, size_t needed_bytes)
_rw_region.print_out_of_space_msg(name, needed_bytes);
_ro_region.print_out_of_space_msg(name, needed_bytes);
vm_exit_during_initialization(err_msg("Unable to allocate from '%s' region", name),
"Please reduce the number of shared classes.");
log_error(cds)("Unable to allocate from '%s' region: Please reduce the number of shared classes.", name);
MetaspaceShared::unrecoverable_writing_error();
}

@ -164,8 +164,8 @@ char* DumpRegion::expand_top_to(char* newtop) {
// This is just a sanity check and should not appear in any real world usage. This
// happens only if you allocate more than 2GB of shared objects and would require
// millions of shared classes.
vm_exit_during_initialization("Out of memory in the CDS archive",
"Please reduce the number of shared classes.");
log_error(cds)("Out of memory in the CDS archive: Please reduce the number of shared classes.");
MetaspaceShared::unrecoverable_writing_error();
}
}
@ -190,8 +190,9 @@ void DumpRegion::commit_to(char* newtop) {
assert(commit <= uncommitted, "sanity");
if (!_vs->expand_by(commit, false)) {
vm_exit_during_initialization(err_msg("Failed to expand shared space to " SIZE_FORMAT " bytes",
need_committed_size));
log_error(cds)("Failed to expand shared space to " SIZE_FORMAT " bytes",
need_committed_size);
MetaspaceShared::unrecoverable_writing_error();
}
const char* which;

@ -367,7 +367,8 @@ void DynamicArchive::check_for_dynamic_dump() {
#define __THEMSG " is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info."
if (RecordDynamicDumpInfo) {
vm_exit_during_initialization("-XX:+RecordDynamicDumpInfo" __THEMSG, nullptr);
log_error(cds)("-XX:+RecordDynamicDumpInfo%s", __THEMSG);
MetaspaceShared::unrecoverable_loading_error();
} else {
assert(ArchiveClassesAtExit != nullptr, "sanity");
log_warning(cds)("-XX:ArchiveClassesAtExit" __THEMSG);

@ -80,29 +80,6 @@
#define O_BINARY 0 // otherwise do nothing.
#endif
// Complain and stop. All error conditions occurring during the writing of
// an archive file should stop the process. Unrecoverable errors during
// the reading of the archive file should stop the process.
static void fail_exit(const char *msg, va_list ap) {
// This occurs very early during initialization: tty is not initialized.
jio_fprintf(defaultStream::error_stream(),
"An error has occurred while processing the"
" shared archive file.\n");
jio_vfprintf(defaultStream::error_stream(), msg, ap);
jio_fprintf(defaultStream::error_stream(), "\n");
// Do not change the text of the below message because some tests check for it.
vm_exit_during_initialization("Unable to use shared archive.", nullptr);
}
void FileMapInfo::fail_stop(const char *msg, ...) {
va_list ap;
va_start(ap, msg);
fail_exit(msg, ap); // Never returns.
va_end(ap); // for completeness.
}
// Fill in the fileMapInfo structure with data about this VM instance.
// This method copies the vm version info into header_version. If the version is too
@ -367,7 +344,8 @@ void SharedClassPathEntry::init(bool is_modules_image,
//
// If we can't access a jar file in the boot path, then we can't
// make assumptions about where classes get loaded from.
FileMapInfo::fail_stop("Unable to open file %s.", cpe->name());
log_error(cds)("Unable to open file %s.", cpe->name());
MetaspaceShared::unrecoverable_loading_error();
}
// No need to save the name of the module file, as it will be computed at run time
@ -1097,7 +1075,8 @@ bool FileMapInfo::validate_shared_path_table() {
const char* hint_msg = log_is_enabled(Info, class, path) ?
"" : " (hint: enable -Xlog:class+path=info to diagnose the failure)";
if (RequireSharedSpaces) {
fail_stop("%s%s", mismatch_msg, hint_msg);
log_error(cds)("%s%s", mismatch_msg, hint_msg);
MetaspaceShared::unrecoverable_loading_error();
} else {
log_warning(cds)("%s%s", mismatch_msg, hint_msg);
}
@ -1447,7 +1426,8 @@ bool FileMapInfo::init_from_file(int fd) {
void FileMapInfo::seek_to_position(size_t pos) {
if (os::lseek(_fd, (long)pos, SEEK_SET) < 0) {
fail_stop("Unable to seek to position " SIZE_FORMAT, pos);
log_error(cds)("Unable to seek to position %ld", pos);
MetaspaceShared::unrecoverable_loading_error();
}
}
@ -1493,8 +1473,9 @@ void FileMapInfo::open_for_write() {
remove(_full_path);
int fd = os::open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444);
if (fd < 0) {
fail_stop("Unable to create shared archive file %s: (%s).", _full_path,
os::strerror(errno));
log_error(cds)("Unable to create shared archive file %s: (%s).", _full_path,
os::strerror(errno));
MetaspaceShared::unrecoverable_writing_error();
}
_fd = fd;
_file_open = true;
@ -1731,11 +1712,12 @@ size_t FileMapInfo::write_heap_regions(GrowableArray<MemRegion>* regions,
int arr_len = regions == nullptr ? 0 : regions->length();
if (arr_len > max_num_regions) {
fail_stop("Unable to write archive heap memory regions: "
"number of memory regions exceeds maximum due to fragmentation. "
"Please increase java heap size "
"(current MaxHeapSize is " SIZE_FORMAT ", InitialHeapSize is " SIZE_FORMAT ").",
MaxHeapSize, InitialHeapSize);
log_error(cds)("Unable to write archive heap memory regions: "
"number of memory regions exceeds maximum due to fragmentation. "
"Please increase java heap size "
"(current MaxHeapSize is " SIZE_FORMAT ", InitialHeapSize is " SIZE_FORMAT ").",
MaxHeapSize, InitialHeapSize);
MetaspaceShared::unrecoverable_writing_error();
}
size_t total_size = 0;
@ -1769,7 +1751,7 @@ void FileMapInfo::write_bytes(const void* buffer, size_t nbytes) {
// If the shared archive is corrupted, close it and remove it.
close();
remove(_full_path);
fail_stop("Unable to write to shared archive file.");
MetaspaceShared::unrecoverable_writing_error("Unable to write to shared archive file.");
}
_file_offset += nbytes;
}
@ -1810,7 +1792,7 @@ void FileMapInfo::write_bytes_aligned(const void* buffer, size_t nbytes) {
void FileMapInfo::close() {
if (_file_open) {
if (::close(_fd) < 0) {
fail_stop("Unable to close the shared archive file.");
MetaspaceShared::unrecoverable_loading_error("Unable to close the shared archive file.");
}
_file_open = false;
_fd = -1;
@ -2537,7 +2519,7 @@ void FileMapInfo::unmap_region(int i) {
void FileMapInfo::assert_mark(bool check) {
if (!check) {
fail_stop("Mark mismatch while restoring from shared file.");
MetaspaceShared::unrecoverable_loading_error("Mark mismatch while restoring from shared file.");
}
}

@ -482,8 +482,6 @@ public:
// Remap the shared readonly space to shared readwrite, private.
bool remap_shared_readonly_as_readwrite();
// Errors.
static void fail_stop(const char *msg, ...) ATTRIBUTE_PRINTF(1, 2);
static bool memory_mapping_failed() {
CDS_ONLY(return _memory_mapping_failed;)
NOT_CDS(return false;)

@ -735,7 +735,7 @@ void KlassSubGraphInfo::check_allowed_klass(InstanceKlass* ik) {
ResourceMark rm;
log_error(cds, heap)("Class %s not allowed in archive heap. Must be in java.base%s",
ik->external_name(), extra_msg);
os::_exit(1);
MetaspaceShared::unrecoverable_writing_error();
}
bool KlassSubGraphInfo::is_non_early_klass(Klass* k) {
@ -1213,7 +1213,7 @@ bool HeapShared::archive_reachable_objects_from(int level,
// these objects that are referenced (directly or indirectly) by static fields.
ResourceMark rm;
log_error(cds, heap)("Cannot archive object of class %s", orig_obj->klass()->external_name());
os::_exit(1);
MetaspaceShared::unrecoverable_writing_error();
}
// java.lang.Class instances cannot be included in an archived object sub-graph. We only support
@ -1223,7 +1223,7 @@ bool HeapShared::archive_reachable_objects_from(int level,
// object that is referenced (directly or indirectly) by static fields.
if (java_lang_Class::is_instance(orig_obj) && subgraph_info != _default_subgraph_info) {
log_error(cds, heap)("(%d) Unknown java.lang.Class object is in the archived sub-graph", level);
os::_exit(1);
MetaspaceShared::unrecoverable_writing_error();
}
if (has_been_seen_during_subgraph_recording(orig_obj)) {
@ -1252,7 +1252,7 @@ bool HeapShared::archive_reachable_objects_from(int level,
// We don't know how to handle an object that has been archived, but some of its reachable
// objects cannot be archived. Bail out for now. We might need to fix this in the future if
// we have a real use case.
os::_exit(1);
MetaspaceShared::unrecoverable_writing_error();
}
}
}

@ -267,8 +267,8 @@ void MetaspaceShared::initialize_for_static_dump() {
size_t symbol_rs_size = LP64_ONLY(3 * G) NOT_LP64(128 * M);
_symbol_rs = ReservedSpace(symbol_rs_size);
if (!_symbol_rs.is_reserved()) {
vm_exit_during_initialization("Unable to reserve memory for symbols",
err_msg(SIZE_FORMAT " bytes.", symbol_rs_size));
log_error(cds)("Unable to reserve memory for symbols: %ld bytes.", symbol_rs_size);
MetaspaceShared::unrecoverable_writing_error();
}
_symbol_region.init(&_symbol_rs, &_symbol_vs);
}
@ -309,7 +309,8 @@ void MetaspaceShared::read_extra_data(JavaThread* current, const char* filename)
ResourceMark rm(current);
if (utf8_length == 0x7fffffff) {
// buf_len will overflown 32-bit value.
vm_exit_during_initialization(err_msg("string length too large: %d", utf8_length));
log_error(cds)("string length too large: %d", utf8_length);
MetaspaceShared::unrecoverable_loading_error();
}
int buf_len = utf8_length+1;
char* utf8_buffer = NEW_RESOURCE_ARRAY(char, buf_len);
@ -564,10 +565,7 @@ void VM_PopulateDumpSharedSpace::doit() {
"for testing purposes only and should not be used in a production environment");
}
// There may be pending VM operations. We have changed some global states
// (such as vmClasses::_klasses) that may cause these VM operations
// to fail. For safety, forget these operations and exit the VM directly.
os::_exit(0);
MetaspaceShared::exit_after_static_dump();
}
class CollectCLDClosure : public CLDClosure {
@ -677,12 +675,13 @@ void MetaspaceShared::preload_and_dump() {
preload_and_dump_impl(THREAD);
if (HAS_PENDING_EXCEPTION) {
if (PENDING_EXCEPTION->is_a(vmClasses::OutOfMemoryError_klass())) {
vm_direct_exit(-1, err_msg("Out of memory. Please run with a larger Java heap, current MaxHeapSize = "
SIZE_FORMAT "M", MaxHeapSize/M));
log_error(cds)("Out of memory. Please run with a larger Java heap, current MaxHeapSize = "
SIZE_FORMAT "M", MaxHeapSize/M);
MetaspaceShared::unrecoverable_writing_error();
} else {
log_error(cds)("%s: %s", PENDING_EXCEPTION->klass()->external_name(),
java_lang_String::as_utf8_string(java_lang_Throwable::message(PENDING_EXCEPTION)));
vm_direct_exit(-1, "VM exits due to exception, use -Xlog:cds,exceptions=trace for detail");
MetaspaceShared::unrecoverable_writing_error("VM exits due to exception, use -Xlog:cds,exceptions=trace for detail");
}
} else {
// On success, the VM_PopulateDumpSharedSpace op should have
@ -902,6 +901,37 @@ bool MetaspaceShared::is_shared_dynamic(void* p) {
}
}
// This function is called when the JVM is unable to load the specified archive(s) due to one
// of the following conditions.
// - There's an error that indicates that the archive(s) files were corrupt or otherwise damaged.
// - When -XX:+RequireSharedSpaces is specified, AND the JVM cannot load the archive(s) due
// to version or classpath mismatch.
void MetaspaceShared::unrecoverable_loading_error(const char* message) {
log_error(cds)("An error has occurred while processing the shared archive file.");
if (message != nullptr) {
log_error(cds)("%s", message);
}
vm_exit_during_initialization("Unable to use shared archive.", nullptr);
}
// This function is called when the JVM is unable to write the specified CDS archive due to an
// unrecoverable error.
void MetaspaceShared::unrecoverable_writing_error(const char* message) {
log_error(cds)("An error has occurred while writing the shared archive file.");
if (message != nullptr) {
log_error(cds)("%s", message);
}
vm_exit(1);
}
// We have finished dumping the static archive. At this point, there may be pending VM
// operations. We have changed some global states (such as vmClasses::_klasses) that
// may cause these VM operations to fail. For safety, forget these operations and
// exit the VM directly.
void MetaspaceShared::exit_after_static_dump() {
os::_exit(0);
}
void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
assert(UseSharedSpaces, "Must be called when UseSharedSpaces is enabled");
MapArchiveResult result = MAP_ARCHIVE_OTHER_FAILURE;
@ -950,9 +980,9 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
DynamicDumpSharedSpaces = false;
log_info(cds)("Unable to map shared spaces");
if (PrintSharedArchiveAndExit) {
vm_exit_during_initialization("Unable to use shared archive.");
MetaspaceShared::unrecoverable_loading_error("Unable to use shared archive.");
} else if (RequireSharedSpaces) {
FileMapInfo::fail_stop("Unable to map shared spaces");
MetaspaceShared::unrecoverable_loading_error("Unable to map shared spaces");
}
}
@ -967,7 +997,7 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
delete dynamic_mapinfo;
}
if (RequireSharedSpaces && has_failed) {
FileMapInfo::fail_stop("Unable to map shared spaces");
MetaspaceShared::unrecoverable_loading_error("Unable to map shared spaces");
}
}
@ -995,7 +1025,7 @@ FileMapInfo* MetaspaceShared::open_dynamic_archive() {
if (!mapinfo->initialize()) {
delete(mapinfo);
if (RequireSharedSpaces) {
FileMapInfo::fail_stop("Failed to initialize dynamic archive");
MetaspaceShared::unrecoverable_loading_error("Failed to initialize dynamic archive");
}
return nullptr;
}

@ -116,6 +116,10 @@ public:
static bool is_shared_dynamic(void* p) NOT_CDS_RETURN_(false);
static void unrecoverable_loading_error(const char* message = nullptr);
static void unrecoverable_writing_error(const char* message = nullptr);
static void exit_after_static_dump();
static void serialize(SerializeClosure* sc) NOT_CDS_RETURN;
// JVM/TI RedefineClasses() support:

@ -797,7 +797,7 @@ void StringTable::allocate_shared_strings_array(TRAPS) {
// refer to more than 16384 * 16384 = 26M interned strings! Not a practical concern
// but bail out for safety.
log_error(cds)("Too many strings to be archived: " SIZE_FORMAT, _items_count);
os::_exit(1);
MetaspaceShared::unrecoverable_writing_error();
}
objArrayOop primary = oopFactory::new_objArray(vmClasses::Object_klass(), primary_array_length, CHECK);