8238000: Crash in ClassLoader::record_result while dynamic dumping netty

Make a copy of the _shared_path_table for use during dynamic CDS dump.

Reviewed-by: iklam, minqi
This commit is contained in:
Calvin Cheung 2020-03-12 16:05:07 -07:00
parent 0610992a8f
commit 38940d166a
4 changed files with 53 additions and 11 deletions

View file

@ -956,7 +956,7 @@ void DynamicArchiveBuilder::relocate_buffer_to_target() {
RelocateBufferToTarget patcher(this, (address*)_alloc_bottom, _buffer_to_target_delta); RelocateBufferToTarget patcher(this, (address*)_alloc_bottom, _buffer_to_target_delta);
ArchivePtrMarker::ptrmap()->iterate(&patcher); ArchivePtrMarker::ptrmap()->iterate(&patcher);
Array<u8>* table = FileMapInfo::shared_path_table().table(); Array<u8>* table = FileMapInfo::saved_shared_path_table().table();
SharedPathTable runtime_table(to_target(table), FileMapInfo::shared_path_table().size()); SharedPathTable runtime_table(to_target(table), FileMapInfo::shared_path_table().size());
_header->set_shared_path_table(runtime_table); _header->set_shared_path_table(runtime_table);

View file

@ -293,6 +293,23 @@ void SharedClassPathEntry::set_name(const char* name, TRAPS) {
strcpy(_name->data(), name); strcpy(_name->data(), name);
} }
void SharedClassPathEntry::copy_from(SharedClassPathEntry* ent, ClassLoaderData* loader_data, TRAPS) {
_type = ent->_type;
_timestamp = ent->_timestamp;
_filesize = ent->_filesize;
_from_class_path_attr = ent->_from_class_path_attr;
set_name(ent->name(), THREAD);
if (ent->is_jar() && !ent->is_signed() && ent->manifest() != NULL) {
Array<u1>* buf = MetadataFactory::new_array<u1>(loader_data,
ent->manifest_size(),
THREAD);
char* p = (char*)(buf->data());
memcpy(p, ent->manifest(), ent->manifest_size());
set_manifest(buf);
}
}
const char* SharedClassPathEntry::name() const { const char* SharedClassPathEntry::name() const {
if (UseSharedSpaces && is_modules_image()) { if (UseSharedSpaces && is_modules_image()) {
// In order to validate the runtime modules image file size against the archived // In order to validate the runtime modules image file size against the archived
@ -381,10 +398,26 @@ void SharedPathTable::dumptime_init(ClassLoaderData* loader_data, Thread* THREAD
num_entries += FileMapInfo::num_non_existent_class_paths(); num_entries += FileMapInfo::num_non_existent_class_paths();
size_t bytes = entry_size * num_entries; size_t bytes = entry_size * num_entries;
_table = MetadataFactory::new_array<u8>(loader_data, (int)(bytes + 7 / 8), THREAD); _table = MetadataFactory::new_array<u8>(loader_data, (int)bytes, THREAD);
_size = num_entries; _size = num_entries;
} }
// Make a copy of the _shared_path_table for use during dynamic CDS dump.
// It is needed because some Java code continues to execute after dynamic dump has finished.
// However, during dynamic dump, we have modified FileMapInfo::_shared_path_table so
// FileMapInfo::shared_path(i) returns incorrect information in ClassLoader::record_result().
void FileMapInfo::copy_shared_path_table(ClassLoaderData* loader_data, Thread* THREAD) {
size_t entry_size = sizeof(SharedClassPathEntry);
size_t bytes = entry_size * _shared_path_table.size();
_saved_shared_path_table = SharedPathTable(MetadataFactory::new_array<u8>(loader_data, (int)bytes, THREAD),
_shared_path_table.size());
for (int i = 0; i < _shared_path_table.size(); i++) {
_saved_shared_path_table.path_at(i)->copy_from(shared_path(i), loader_data, THREAD);
}
}
void FileMapInfo::allocate_shared_path_table() { void FileMapInfo::allocate_shared_path_table() {
Arguments::assert_is_dumping_archive(); Arguments::assert_is_dumping_archive();
@ -409,6 +442,8 @@ void FileMapInfo::allocate_shared_path_table() {
} }
assert(i == _shared_path_table.size(), "number of shared path entry mismatch"); assert(i == _shared_path_table.size(), "number of shared path entry mismatch");
copy_shared_path_table(loader_data, THREAD);
} }
int FileMapInfo::add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS) { int FileMapInfo::add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS) {
@ -937,10 +972,6 @@ bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name,
return true; return true;
} }
void FileMapInfo::restore_shared_path_table() {
_shared_path_table = _current_info->header()->shared_path_table();
}
// Read the FileMapInfo information from the file. // Read the FileMapInfo information from the file.
bool FileMapInfo::init_from_file(int fd) { bool FileMapInfo::init_from_file(int fd) {
@ -1926,14 +1957,19 @@ void FileMapInfo::assert_mark(bool check) {
} }
} }
void FileMapInfo::metaspace_pointers_do(MetaspaceClosure* it) { void FileMapInfo::metaspace_pointers_do(MetaspaceClosure* it, bool use_copy) {
_shared_path_table.metaspace_pointers_do(it); if (use_copy) {
_saved_shared_path_table.metaspace_pointers_do(it);
} else {
_shared_path_table.metaspace_pointers_do(it);
}
} }
FileMapInfo* FileMapInfo::_current_info = NULL; FileMapInfo* FileMapInfo::_current_info = NULL;
FileMapInfo* FileMapInfo::_dynamic_archive_info = NULL; FileMapInfo* FileMapInfo::_dynamic_archive_info = NULL;
bool FileMapInfo::_heap_pointers_need_patching = false; bool FileMapInfo::_heap_pointers_need_patching = false;
SharedPathTable FileMapInfo::_shared_path_table; SharedPathTable FileMapInfo::_shared_path_table;
SharedPathTable FileMapInfo::_saved_shared_path_table;
bool FileMapInfo::_validating_shared_path_table = false; bool FileMapInfo::_validating_shared_path_table = false;
bool FileMapInfo::_memory_mapping_failed = false; bool FileMapInfo::_memory_mapping_failed = false;
GrowableArray<const char*>* FileMapInfo::_non_existent_class_paths = NULL; GrowableArray<const char*>* FileMapInfo::_non_existent_class_paths = NULL;

View file

@ -95,6 +95,7 @@ public:
_manifest = manifest; _manifest = manifest;
} }
bool check_non_existent() const; bool check_non_existent() const;
void copy_from(SharedClassPathEntry* ent, ClassLoaderData* loader_data, TRAPS);
}; };
struct ArchiveHeapOopmapInfo { struct ArchiveHeapOopmapInfo {
@ -335,6 +336,7 @@ private:
// TODO: Probably change the following to be non-static // TODO: Probably change the following to be non-static
static SharedPathTable _shared_path_table; static SharedPathTable _shared_path_table;
static SharedPathTable _saved_shared_path_table;
static bool _validating_shared_path_table; static bool _validating_shared_path_table;
// FileMapHeader describes the shared space data in the file to be // FileMapHeader describes the shared space data in the file to be
@ -356,9 +358,12 @@ public:
static SharedPathTable shared_path_table() { static SharedPathTable shared_path_table() {
return _shared_path_table; return _shared_path_table;
} }
void restore_shared_path_table(); static SharedPathTable saved_shared_path_table() {
return _saved_shared_path_table;
}
bool init_from_file(int fd); bool init_from_file(int fd);
static void metaspace_pointers_do(MetaspaceClosure* it); static void metaspace_pointers_do(MetaspaceClosure* it, bool use_copy = true);
void log_paths(const char* msg, int start_idx, int end_idx); void log_paths(const char* msg, int start_idx, int end_idx);
@ -482,6 +487,7 @@ public:
static void stop_sharing_and_unmap(const char* msg); static void stop_sharing_and_unmap(const char* msg);
static void allocate_shared_path_table(); static void allocate_shared_path_table();
static void copy_shared_path_table(ClassLoaderData* loader_data, Thread* THREAD);
static int add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS); static int add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS);
static void check_nonempty_dir_in_shared_path_table(); static void check_nonempty_dir_in_shared_path_table();
bool validate_shared_path_table(); bool validate_shared_path_table();

View file

@ -1375,7 +1375,7 @@ public:
it->push(_global_klass_objects->adr_at(i)); it->push(_global_klass_objects->adr_at(i));
} }
} }
FileMapInfo::metaspace_pointers_do(it); FileMapInfo::metaspace_pointers_do(it, false);
SystemDictionaryShared::dumptime_classes_do(it); SystemDictionaryShared::dumptime_classes_do(it);
Universe::metaspace_pointers_do(it); Universe::metaspace_pointers_do(it);
SymbolTable::metaspace_pointers_do(it); SymbolTable::metaspace_pointers_do(it);