8316994: Avoid modifying ClassLoader and Module objects during -Xshare:dump
Reviewed-by: matsaave, ccheung
This commit is contained in:
parent
83c0e45160
commit
52073b27a3
@ -26,6 +26,7 @@
|
||||
#include "cds/archiveHeapWriter.hpp"
|
||||
#include "cds/filemap.hpp"
|
||||
#include "cds/heapShared.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "memory/iterator.inline.hpp"
|
||||
#include "memory/oopFactory.hpp"
|
||||
@ -317,6 +318,12 @@ size_t ArchiveHeapWriter::get_filler_size_at(address buffered_addr) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void update_buffered_object_field(address buffered_obj, int field_offset, T value) {
|
||||
T* field_addr = cast_to_oop(buffered_obj)->field_addr<T>(field_offset);
|
||||
*field_addr = value;
|
||||
}
|
||||
|
||||
size_t ArchiveHeapWriter::copy_one_source_obj_to_buffer(oop src_obj) {
|
||||
assert(!is_too_large_to_archive(src_obj), "already checked");
|
||||
size_t byte_size = src_obj->size() * HeapWordSize;
|
||||
@ -342,6 +349,20 @@ size_t ArchiveHeapWriter::copy_one_source_obj_to_buffer(oop src_obj) {
|
||||
assert(is_object_aligned(byte_size), "sanity");
|
||||
memcpy(to, from, byte_size);
|
||||
|
||||
// These native pointers will be restored explicitly at run time.
|
||||
if (java_lang_Module::is_instance(src_obj)) {
|
||||
update_buffered_object_field<ModuleEntry*>(to, java_lang_Module::module_entry_offset(), nullptr);
|
||||
} else if (java_lang_ClassLoader::is_instance(src_obj)) {
|
||||
#ifdef ASSERT
|
||||
// We only archive these loaders
|
||||
if (src_obj != SystemDictionary::java_platform_loader() &&
|
||||
src_obj != SystemDictionary::java_system_loader()) {
|
||||
assert(src_obj->klass()->name()->equals("jdk/internal/loader/ClassLoaders$BootClassLoader"), "must be");
|
||||
}
|
||||
#endif
|
||||
update_buffered_object_field<ClassLoaderData*>(to, java_lang_ClassLoader::loader_data_offset(), nullptr);
|
||||
}
|
||||
|
||||
size_t buffered_obj_offset = _buffer_used;
|
||||
_buffer_used = new_used;
|
||||
|
||||
|
@ -135,8 +135,6 @@ OopHandle HeapShared::_roots;
|
||||
OopHandle HeapShared::_scratch_basic_type_mirrors[T_VOID+1];
|
||||
MetaspaceObjToOopHandleTable* HeapShared::_scratch_java_mirror_table = nullptr;
|
||||
MetaspaceObjToOopHandleTable* HeapShared::_scratch_references_table = nullptr;
|
||||
ClassLoaderData* HeapShared::_saved_java_platform_loader_data = nullptr;
|
||||
ClassLoaderData* HeapShared::_saved_java_system_loader_data = nullptr;
|
||||
|
||||
static bool is_subgraph_root_class_of(ArchivableStaticFieldInfo fields[], InstanceKlass* ik) {
|
||||
for (int i = 0; fields[i].valid(); i++) {
|
||||
@ -295,34 +293,14 @@ bool HeapShared::archive_object(oop obj) {
|
||||
p2i(obj), obj->klass()->external_name());
|
||||
}
|
||||
|
||||
if (java_lang_Module::is_instance(obj)) {
|
||||
if (Modules::check_module_oop(obj)) {
|
||||
if (java_lang_Module::is_instance(obj) && Modules::check_archived_module_oop(obj)) {
|
||||
Modules::update_oops_in_archived_module(obj, append_root(obj));
|
||||
}
|
||||
java_lang_Module::set_module_entry(obj, nullptr);
|
||||
} else if (java_lang_ClassLoader::is_instance(obj)) {
|
||||
// class_data will be restored explicitly at run time and after dumptime
|
||||
guarantee(obj == SystemDictionary::java_platform_loader() ||
|
||||
obj == SystemDictionary::java_system_loader() ||
|
||||
java_lang_ClassLoader::loader_data(obj) == nullptr, "must be");
|
||||
if (obj == SystemDictionary::java_platform_loader()) {
|
||||
_saved_java_platform_loader_data = java_lang_ClassLoader::loader_data_acquire(SystemDictionary::java_platform_loader());
|
||||
} else if (obj == SystemDictionary::java_system_loader()) {
|
||||
_saved_java_system_loader_data = java_lang_ClassLoader::loader_data_acquire(SystemDictionary::java_system_loader());
|
||||
}
|
||||
java_lang_ClassLoader::release_set_loader_data(obj, nullptr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void HeapShared::restore_loader_data() {
|
||||
log_info(cds)("Restoring java platform and system loaders");
|
||||
java_lang_ClassLoader::release_set_loader_data(SystemDictionary::java_platform_loader(), _saved_java_platform_loader_data);
|
||||
java_lang_ClassLoader::release_set_loader_data(SystemDictionary::java_system_loader(), _saved_java_system_loader_data);
|
||||
}
|
||||
|
||||
class MetaspaceObjToOopHandleTable: public ResourceHashtable<MetaspaceObj*, OopHandle,
|
||||
36137, // prime number
|
||||
AnyObj::C_HEAP,
|
||||
|
@ -283,9 +283,6 @@ private:
|
||||
static MetaspaceObjToOopHandleTable* _scratch_java_mirror_table;
|
||||
static MetaspaceObjToOopHandleTable* _scratch_references_table;
|
||||
|
||||
static ClassLoaderData* _saved_java_platform_loader_data;
|
||||
static ClassLoaderData* _saved_java_system_loader_data;
|
||||
|
||||
static void init_seen_objects_table() {
|
||||
assert(_seen_objects_table == nullptr, "must be");
|
||||
_seen_objects_table = new (mtClass)SeenObjectsTable();
|
||||
@ -401,7 +398,6 @@ private:
|
||||
static objArrayOop scratch_resolved_references(ConstantPool* src);
|
||||
static void add_scratch_resolved_references(ConstantPool* src, objArrayOop dest) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void init_scratch_objects(TRAPS) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void restore_loader_data() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static bool is_heap_region(int idx) {
|
||||
CDS_JAVA_HEAP_ONLY(return (idx == MetaspaceShared::hp);)
|
||||
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
|
@ -663,13 +663,6 @@ void MetaspaceShared::preload_and_dump() {
|
||||
MetaspaceShared::unrecoverable_writing_error("VM exits due to exception, use -Xlog:cds,exceptions=trace for detail");
|
||||
}
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
// Restore the java loaders that were cleared at dump time
|
||||
if (use_full_module_graph()) {
|
||||
HeapShared::restore_loader_data();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP && defined(_LP64)
|
||||
|
@ -852,6 +852,9 @@ class java_lang_Module {
|
||||
static oop loader(oop module);
|
||||
static void set_loader(oop module, oop value);
|
||||
|
||||
// CDS
|
||||
static int module_entry_offset() { return _module_entry_offset; }
|
||||
|
||||
static oop name(oop module);
|
||||
static void set_name(oop module, oop value);
|
||||
|
||||
@ -1465,7 +1468,9 @@ class java_lang_ClassLoader : AllStatic {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
// Support for CDS
|
||||
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
static int loader_data_offset() { return _loader_data_offset; }
|
||||
|
||||
static ClassLoaderData* loader_data_acquire(oop loader);
|
||||
static ClassLoaderData* loader_data(oop loader);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2023, 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
|
||||
@ -483,7 +483,7 @@ static bool _seen_system_unnamed_module = false;
|
||||
// Validate the states of an java.lang.Module oop to be archived.
|
||||
//
|
||||
// Returns true iff the oop has an archived ModuleEntry.
|
||||
bool Modules::check_module_oop(oop orig_module_obj) {
|
||||
bool Modules::check_archived_module_oop(oop orig_module_obj) {
|
||||
assert(DumpSharedSpaces, "must be");
|
||||
assert(MetaspaceShared::use_full_module_graph(), "must be");
|
||||
assert(java_lang_Module::is_instance(orig_module_obj), "must be");
|
||||
@ -544,7 +544,7 @@ bool Modules::check_module_oop(oop orig_module_obj) {
|
||||
|
||||
void Modules::update_oops_in_archived_module(oop orig_module_obj, int archived_module_root_index) {
|
||||
// This java.lang.Module oop must have an archived ModuleEntry
|
||||
assert(check_module_oop(orig_module_obj) == true, "sanity");
|
||||
assert(check_archived_module_oop(orig_module_obj) == true, "sanity");
|
||||
|
||||
// We remember the oop inside the ModuleEntry::_archived_module_index. At runtime, we use
|
||||
// this index to reinitialize the ModuleEntry inside ModuleEntry::restore_archived_oops().
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2023, 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
|
||||
@ -53,7 +53,7 @@ public:
|
||||
static void define_module(Handle module, jboolean is_open, jstring version,
|
||||
jstring location, jobjectArray packages, TRAPS);
|
||||
|
||||
static bool check_module_oop(oop orig_module_obj) NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
static bool check_archived_module_oop(oop orig_module_obj) NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
static void update_oops_in_archived_module(oop orig_module_obj, int archived_module_root_index)
|
||||
NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void define_archived_modules(Handle h_platform_loader, Handle h_system_loader,
|
||||
|
Loading…
x
Reference in New Issue
Block a user