8230586: Encapsulate fields in filemap.hpp
Reviewed-by: ccheung
This commit is contained in:
parent
99252bd9d6
commit
988ac4fec0
src/hotspot/share
classfile
include
interpreter
memory
prims
test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive
@ -55,7 +55,7 @@ bool ClassLoaderExt::_has_platform_classes = false;
|
||||
void ClassLoaderExt::append_boot_classpath(ClassPathEntry* new_entry) {
|
||||
if (UseSharedSpaces) {
|
||||
warning("Sharing is only supported for boot loader classes because bootstrap classpath has been appended");
|
||||
FileMapInfo::current_info()->header()->set_has_platform_or_app_classes(false);
|
||||
FileMapInfo::current_info()->set_has_platform_or_app_classes(false);
|
||||
}
|
||||
ClassLoader::add_to_boot_append_entries(new_entry);
|
||||
}
|
||||
|
@ -744,11 +744,11 @@ bool SystemDictionaryShared::is_shared_class_visible_for_classloader(
|
||||
}
|
||||
|
||||
bool SystemDictionaryShared::has_platform_or_app_classes() {
|
||||
if (FileMapInfo::current_info()->header()->has_platform_or_app_classes()) {
|
||||
if (FileMapInfo::current_info()->has_platform_or_app_classes()) {
|
||||
return true;
|
||||
}
|
||||
if (DynamicArchive::is_mapped() &&
|
||||
FileMapInfo::dynamic_info()->header()->has_platform_or_app_classes()) {
|
||||
FileMapInfo::dynamic_info()->has_platform_or_app_classes()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -36,22 +36,23 @@
|
||||
#define NUM_CDS_REGIONS 8 // this must be the same as MetaspaceShared::n_regions
|
||||
#define CDS_ARCHIVE_MAGIC 0xf00baba2
|
||||
#define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8
|
||||
#define CURRENT_CDS_ARCHIVE_VERSION 7
|
||||
#define CURRENT_CDS_ARCHIVE_VERSION 8
|
||||
#define INVALID_CDS_ARCHIVE_VERSION -1
|
||||
|
||||
struct CDSFileMapRegion {
|
||||
int _crc; // crc checksum of the current space
|
||||
size_t _file_offset; // sizeof(this) rounded to vm page size
|
||||
int _crc; // crc checksum of the current space
|
||||
size_t _file_offset; // sizeof(this) rounded to vm page size
|
||||
union {
|
||||
char* _base; // copy-on-write base address
|
||||
size_t _offset; // offset from the compressed oop encoding base, only used
|
||||
// by archive heap space
|
||||
char* _base; // copy-on-write base address
|
||||
size_t _offset; // offset from the compressed oop encoding base, only used
|
||||
// by archive heap space
|
||||
} _addr;
|
||||
size_t _used; // for setting space top on read
|
||||
int _read_only; // read only space?
|
||||
int _allow_exec; // executable code in space?
|
||||
void* _oopmap; // bitmap for relocating embedded oops
|
||||
size_t _used; // for setting space top on read
|
||||
int _read_only; // read only space?
|
||||
int _allow_exec; // executable code in space?
|
||||
void* _oopmap; // bitmap for relocating embedded oops
|
||||
size_t _oopmap_size_in_bits;
|
||||
int _is_heap_region; // used in debug build only.
|
||||
};
|
||||
|
||||
struct CDSFileMapHeaderBase {
|
||||
|
@ -208,7 +208,7 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(const methodHan
|
||||
|
||||
address AbstractInterpreter::get_trampoline_code_buffer(AbstractInterpreter::MethodKind kind) {
|
||||
const size_t trampoline_size = SharedRuntime::trampoline_size();
|
||||
address addr = MetaspaceShared::cds_i2i_entry_code_buffers((size_t)(AbstractInterpreter::number_of_method_entries) * trampoline_size);
|
||||
address addr = MetaspaceShared::i2i_entry_code_buffers((size_t)(AbstractInterpreter::number_of_method_entries) * trampoline_size);
|
||||
addr += (size_t)(kind) * trampoline_size;
|
||||
|
||||
return addr;
|
||||
|
@ -652,7 +652,7 @@ public:
|
||||
it->push(&_symbols->at(i));
|
||||
}
|
||||
|
||||
_header->_shared_path_table.metaspace_pointers_do(it);
|
||||
_header->shared_path_table_metaspace_pointers_do(it);
|
||||
|
||||
// Do not call these again, as we have already collected all the classes and symbols
|
||||
// that we want to archive. Also, these calls would corrupt the tables when
|
||||
@ -733,14 +733,13 @@ void DynamicArchiveBuilder::init_header(address reserved_bottom) {
|
||||
init_first_dump_space(reserved_bottom);
|
||||
|
||||
FileMapInfo* mapinfo = new FileMapInfo(false);
|
||||
_header = (DynamicArchiveHeader*)mapinfo->_header;
|
||||
_header = mapinfo->dynamic_header();
|
||||
|
||||
Thread* THREAD = Thread::current();
|
||||
FileMapInfo* base_info = FileMapInfo::current_info();
|
||||
int* crc = _header->_base_archive_crc;
|
||||
*crc++ = base_info->crc(); // base archive header crc
|
||||
_header->set_base_header_crc(base_info->crc());
|
||||
for (int i = 0; i < MetaspaceShared::n_regions; i++) {
|
||||
*crc++ = base_info->space_crc(i);
|
||||
_header->set_base_region_crc(i, base_info->space_crc(i));
|
||||
}
|
||||
_header->populate(base_info, os::vm_allocation_granularity());
|
||||
}
|
||||
@ -907,9 +906,9 @@ void DynamicArchiveBuilder::relocate_buffer_to_target() {
|
||||
RelocateBufferToTarget patcher(this, (address*)_alloc_bottom, _buffer_to_target_delta);
|
||||
_ptrmap.iterate(&patcher);
|
||||
|
||||
Array<u8>* table = _header->_shared_path_table.table();
|
||||
Array<u8>* table = _header->shared_path_table().table();
|
||||
table = to_target(table);
|
||||
_header->_shared_path_table.set_table(table);
|
||||
_header->relocate_shared_path_table(table);
|
||||
}
|
||||
|
||||
static void write_archive_info(FileMapInfo* dynamic_info, DynamicArchiveHeader *header) {
|
||||
@ -933,7 +932,7 @@ void DynamicArchiveBuilder::write_archive(char* read_only_tables_start) {
|
||||
int num_klasses = _klasses->length();
|
||||
int num_symbols = _symbols->length();
|
||||
|
||||
_header->_read_only_tables_start = to_target(read_only_tables_start);
|
||||
_header->set_read_only_tables_start(to_target(read_only_tables_start));
|
||||
|
||||
FileMapInfo* dynamic_info = FileMapInfo::dynamic_info();
|
||||
assert(dynamic_info != NULL, "Sanity");
|
||||
@ -953,10 +952,11 @@ void DynamicArchiveBuilder::write_archive(char* read_only_tables_start) {
|
||||
|
||||
address base = to_target(_alloc_bottom);
|
||||
address top = address(current_dump_space()->top()) + _buffer_to_target_delta;
|
||||
int file_size = int(top - base);
|
||||
size_t file_size = pointer_delta(top, base, sizeof(char));
|
||||
|
||||
log_info(cds, dynamic)("Written dynamic archive " PTR_FORMAT " - " PTR_FORMAT " [%d bytes header, %d bytes total]",
|
||||
p2i(base), p2i(top), (int)_header->_header_size, file_size);
|
||||
log_info(cds, dynamic)("Written dynamic archive " PTR_FORMAT " - " PTR_FORMAT
|
||||
" [" SIZE_FORMAT " bytes header, " SIZE_FORMAT " bytes total]",
|
||||
p2i(base), p2i(top), _header->header_size(), file_size);
|
||||
log_info(cds, dynamic)("%d klasses; %d symbols", num_klasses, num_symbols);
|
||||
}
|
||||
|
||||
@ -1046,8 +1046,8 @@ static DynamicArchiveHeader *_dynamic_header = NULL;
|
||||
DynamicArchiveBuilder* DynamicArchive::_builder = NULL;
|
||||
|
||||
void DynamicArchive::map_failed(FileMapInfo* mapinfo) {
|
||||
if (mapinfo->_header != NULL) {
|
||||
os::free(mapinfo->_header);
|
||||
if (mapinfo->dynamic_header() != NULL) {
|
||||
os::free((void*)mapinfo->dynamic_header());
|
||||
}
|
||||
delete mapinfo;
|
||||
}
|
||||
@ -1081,15 +1081,12 @@ address DynamicArchive::map() {
|
||||
}
|
||||
|
||||
address DynamicArchive::map_impl(FileMapInfo* mapinfo) {
|
||||
|
||||
|
||||
// Read header
|
||||
if (!mapinfo->initialize(false)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_dynamic_header = (DynamicArchiveHeader*)mapinfo->header();
|
||||
|
||||
_dynamic_header = mapinfo->dynamic_header();
|
||||
int regions[] = {MetaspaceShared::rw,
|
||||
MetaspaceShared::ro,
|
||||
MetaspaceShared::mc};
|
||||
@ -1111,7 +1108,7 @@ address DynamicArchive::map_impl(FileMapInfo* mapinfo) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
intptr_t* buffer = (intptr_t*)_dynamic_header->_read_only_tables_start;
|
||||
intptr_t* buffer = (intptr_t*)_dynamic_header->read_only_tables_start();
|
||||
ReadClosure rc(&buffer);
|
||||
SymbolTable::serialize_shared_table_header(&rc, false);
|
||||
SystemDictionaryShared::serialize_dictionary_headers(&rc, false);
|
||||
@ -1122,18 +1119,17 @@ address DynamicArchive::map_impl(FileMapInfo* mapinfo) {
|
||||
bool DynamicArchive::validate(FileMapInfo* dynamic_info) {
|
||||
// Check if the recorded base archive matches with the current one
|
||||
FileMapInfo* base_info = FileMapInfo::current_info();
|
||||
DynamicArchiveHeader* dynamic_header = (DynamicArchiveHeader*)dynamic_info->header();
|
||||
int* crc = dynamic_header->_base_archive_crc;
|
||||
DynamicArchiveHeader* dynamic_header = dynamic_info->dynamic_header();
|
||||
|
||||
// Check the header crc
|
||||
if (*crc++ != base_info->crc()) {
|
||||
if (dynamic_header->base_header_crc() != base_info->crc()) {
|
||||
FileMapInfo::fail_continue("Archive header checksum verification failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check each space's crc
|
||||
for (int i = 0; i < MetaspaceShared::n_regions; i++) {
|
||||
if (*crc++ != base_info->space_crc(i)) {
|
||||
if (dynamic_header->base_region_crc(i) != base_info->space_crc(i)) {
|
||||
FileMapInfo::fail_continue("Archive region #%d checksum verification failed.", i);
|
||||
return false;
|
||||
}
|
||||
|
@ -37,12 +37,24 @@
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/resourceHash.hpp"
|
||||
|
||||
// We want to include all archive header information in the dynamic archive.
|
||||
// This helps simplify the process if the base layer archive is missing at
|
||||
// dynamic archiving time.
|
||||
struct DynamicArchiveHeader : public FileMapHeader {
|
||||
// crc for the base archive header and regions
|
||||
int _base_archive_crc[MetaspaceShared::n_regions+1];
|
||||
class DynamicArchiveHeader : public FileMapHeader {
|
||||
friend class CDSOffsets;
|
||||
private:
|
||||
int _base_header_crc;
|
||||
int _base_region_crc[MetaspaceShared::n_regions];
|
||||
|
||||
public:
|
||||
int base_header_crc() const { return _base_header_crc; }
|
||||
int base_region_crc(int i) const {
|
||||
assert(is_valid_region(i), "must be");
|
||||
return _base_region_crc[i];
|
||||
}
|
||||
|
||||
void set_base_header_crc(int c) { _base_header_crc = c; }
|
||||
void set_base_region_crc(int i, int c) {
|
||||
assert(is_valid_region(i), "must be");
|
||||
_base_region_crc[i] = c;
|
||||
}
|
||||
};
|
||||
|
||||
class DynamicArchive : AllStatic {
|
||||
|
@ -192,9 +192,9 @@ FileMapInfo::FileMapInfo(bool is_static) {
|
||||
}
|
||||
_header = (FileMapHeader*)os::malloc(header_size, mtInternal);
|
||||
memset((void*)_header, 0, header_size);
|
||||
_header->_header_size = header_size;
|
||||
_header->_version = INVALID_CDS_ARCHIVE_VERSION;
|
||||
_header->_has_platform_or_app_classes = true;
|
||||
_header->set_header_size(header_size);
|
||||
_header->set_version(INVALID_CDS_ARCHIVE_VERSION);
|
||||
_header->set_has_platform_or_app_classes(true);
|
||||
_file_offset = 0;
|
||||
_file_open = false;
|
||||
}
|
||||
@ -210,7 +210,7 @@ FileMapInfo::~FileMapInfo() {
|
||||
}
|
||||
|
||||
void FileMapInfo::populate_header(size_t alignment) {
|
||||
_header->populate(this, alignment);
|
||||
header()->populate(this, alignment);
|
||||
}
|
||||
|
||||
void FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
|
||||
@ -660,7 +660,7 @@ bool FileMapInfo::validate_boot_class_paths() {
|
||||
char* runtime_boot_path = Arguments::get_sysclasspath();
|
||||
char* rp = skip_first_path_entry(runtime_boot_path);
|
||||
assert(shared_path(0)->is_modules_image(), "first shared_path must be the modules image");
|
||||
int dp_len = _header->_app_class_paths_start_index - 1; // ignore the first path to the module image
|
||||
int dp_len = header()->app_class_paths_start_index() - 1; // ignore the first path to the module image
|
||||
bool mismatch = false;
|
||||
|
||||
bool relaxed_check = !header()->has_platform_or_app_classes();
|
||||
@ -723,7 +723,7 @@ bool FileMapInfo::validate_app_class_paths(int shared_app_paths_len) {
|
||||
// run 1: -cp NE3:a.jar:NE4:b.jar -> a.jar:b.jar -> matched
|
||||
// run 2: -cp x.jar:NE4:b.jar -> x.jar:b.jar -> mismatched
|
||||
|
||||
int j = _header->_app_class_paths_start_index;
|
||||
int j = header()->app_class_paths_start_index();
|
||||
mismatch = check_paths(j, shared_app_paths_len, rp_array);
|
||||
if (mismatch) {
|
||||
return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
|
||||
@ -752,7 +752,7 @@ bool FileMapInfo::validate_shared_path_table() {
|
||||
_validating_shared_path_table = true;
|
||||
|
||||
// Load the shared path table info from the archive header
|
||||
_shared_path_table = _header->_shared_path_table;
|
||||
_shared_path_table = header()->shared_path_table();
|
||||
if (DynamicDumpSharedSpaces) {
|
||||
// Only support dynamic dumping with the usage of the default CDS archive
|
||||
// or a simple base archive.
|
||||
@ -762,30 +762,30 @@ bool FileMapInfo::validate_shared_path_table() {
|
||||
// When dynamic archiving is enabled, the _shared_path_table is overwritten
|
||||
// to include the application path and stored in the top layer archive.
|
||||
assert(shared_path(0)->is_modules_image(), "first shared_path must be the modules image");
|
||||
if (_header->_app_class_paths_start_index > 1) {
|
||||
if (header()->app_class_paths_start_index() > 1) {
|
||||
DynamicDumpSharedSpaces = false;
|
||||
warning(
|
||||
"Dynamic archiving is disabled because base layer archive has appended boot classpath");
|
||||
}
|
||||
if (_header->_num_module_paths > 0) {
|
||||
if (header()->num_module_paths() > 0) {
|
||||
DynamicDumpSharedSpaces = false;
|
||||
warning(
|
||||
"Dynamic archiving is disabled because base layer archive has module path");
|
||||
}
|
||||
}
|
||||
|
||||
log_paths("Expecting BOOT path=", 0, _header->_app_class_paths_start_index);
|
||||
log_paths("Expecting -Djava.class.path=", _header->_app_class_paths_start_index, _header->_app_module_paths_start_index);
|
||||
log_paths("Expecting BOOT path=", 0, header()->app_class_paths_start_index());
|
||||
log_paths("Expecting -Djava.class.path=", header()->app_class_paths_start_index(), header()->app_module_paths_start_index());
|
||||
|
||||
int module_paths_start_index = _header->_app_module_paths_start_index;
|
||||
int module_paths_start_index = header()->app_module_paths_start_index();
|
||||
int shared_app_paths_len = 0;
|
||||
|
||||
// validate the path entries up to the _max_used_path_index
|
||||
for (int i=0; i < _header->_max_used_path_index + 1; i++) {
|
||||
for (int i=0; i < header()->max_used_path_index() + 1; i++) {
|
||||
if (i < module_paths_start_index) {
|
||||
if (shared_path(i)->validate()) {
|
||||
// Only count the app class paths not from the "Class-path" attribute of a jar manifest.
|
||||
if (!shared_path(i)->from_class_path_attr() && i >= _header->_app_class_paths_start_index) {
|
||||
if (!shared_path(i)->from_class_path_attr() && i >= header()->app_class_paths_start_index()) {
|
||||
shared_app_paths_len++;
|
||||
}
|
||||
log_info(class, path)("ok");
|
||||
@ -807,7 +807,7 @@ bool FileMapInfo::validate_shared_path_table() {
|
||||
}
|
||||
}
|
||||
|
||||
if (_header->_max_used_path_index == 0) {
|
||||
if (header()->max_used_path_index() == 0) {
|
||||
// default archive only contains the module image in the bootclasspath
|
||||
assert(shared_path(0)->is_modules_image(), "first shared_path must be the modules image");
|
||||
} else {
|
||||
@ -841,14 +841,14 @@ void FileMapInfo::validate_non_existent_class_paths() {
|
||||
// app classes).
|
||||
|
||||
assert(UseSharedSpaces, "runtime only");
|
||||
for (int i = _header->_app_module_paths_start_index + _header->_num_module_paths;
|
||||
for (int i = header()->app_module_paths_start_index() + header()->num_module_paths();
|
||||
i < get_number_of_shared_paths();
|
||||
i++) {
|
||||
SharedClassPathEntry* ent = shared_path(i);
|
||||
if (!ent->check_non_existent()) {
|
||||
warning("Archived non-system classes are disabled because the "
|
||||
"file %s exists", ent->name());
|
||||
_header->_has_platform_or_app_classes = false;
|
||||
header()->set_has_platform_or_app_classes(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -874,7 +874,7 @@ bool FileMapInfo::check_archive(const char* archive_name, bool is_static) {
|
||||
}
|
||||
if (is_static) {
|
||||
FileMapHeader* static_header = (FileMapHeader*)header;
|
||||
if (static_header->_magic != CDS_ARCHIVE_MAGIC) {
|
||||
if (static_header->magic() != CDS_ARCHIVE_MAGIC) {
|
||||
os::free(header);
|
||||
os::close(fd);
|
||||
vm_exit_during_initialization("Not a base shared archive", archive_name);
|
||||
@ -882,7 +882,7 @@ bool FileMapInfo::check_archive(const char* archive_name, bool is_static) {
|
||||
}
|
||||
} else {
|
||||
DynamicArchiveHeader* dynamic_header = (DynamicArchiveHeader*)header;
|
||||
if (dynamic_header->_magic != CDS_DYNAMIC_ARCHIVE_MAGIC) {
|
||||
if (dynamic_header->magic() != CDS_DYNAMIC_ARCHIVE_MAGIC) {
|
||||
os::free(header);
|
||||
os::close(fd);
|
||||
vm_exit_during_initialization("Not a top shared archive", archive_name);
|
||||
@ -912,18 +912,18 @@ bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name,
|
||||
os::close(fd);
|
||||
return false;
|
||||
}
|
||||
if (dynamic_header->_magic != CDS_DYNAMIC_ARCHIVE_MAGIC) {
|
||||
if (dynamic_header->magic() != CDS_DYNAMIC_ARCHIVE_MAGIC) {
|
||||
// Not a dynamic header, no need to proceed further.
|
||||
*size = 0;
|
||||
os::free(dynamic_header);
|
||||
os::close(fd);
|
||||
return false;
|
||||
}
|
||||
if (dynamic_header->_base_archive_is_default) {
|
||||
if (dynamic_header->base_archive_is_default()) {
|
||||
*base_archive_name = Arguments::get_default_shared_archive_path();
|
||||
} else {
|
||||
// read the base archive name
|
||||
size_t name_size = dynamic_header->_base_archive_name_size;
|
||||
size_t name_size = dynamic_header->base_archive_name_size();
|
||||
if (name_size == 0) {
|
||||
os::free(dynamic_header);
|
||||
os::close(fd);
|
||||
@ -947,14 +947,14 @@ bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name,
|
||||
}
|
||||
|
||||
void FileMapInfo::restore_shared_path_table() {
|
||||
_shared_path_table = _current_info->_header->_shared_path_table;
|
||||
_shared_path_table = _current_info->header()->shared_path_table();
|
||||
}
|
||||
|
||||
// Read the FileMapInfo information from the file.
|
||||
|
||||
bool FileMapInfo::init_from_file(int fd, bool is_static) {
|
||||
size_t sz = is_static ? sizeof(FileMapHeader) : sizeof(DynamicArchiveHeader);
|
||||
size_t n = os::read(fd, _header, (unsigned int)sz);
|
||||
size_t n = os::read(fd, header(), (unsigned int)sz);
|
||||
if (n != sz) {
|
||||
fail_continue("Unable to read the file header.");
|
||||
return false;
|
||||
@ -966,66 +966,68 @@ bool FileMapInfo::init_from_file(int fd, bool is_static) {
|
||||
}
|
||||
|
||||
unsigned int expected_magic = is_static ? CDS_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC;
|
||||
if (_header->_magic != expected_magic) {
|
||||
if (header()->magic() != expected_magic) {
|
||||
log_info(cds)("_magic expected: 0x%08x", expected_magic);
|
||||
log_info(cds)(" actual: 0x%08x", _header->_magic);
|
||||
log_info(cds)(" actual: 0x%08x", header()->magic());
|
||||
FileMapInfo::fail_continue("The shared archive file has a bad magic number.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_header->_version != CURRENT_CDS_ARCHIVE_VERSION) {
|
||||
if (header()->version() != CURRENT_CDS_ARCHIVE_VERSION) {
|
||||
log_info(cds)("_version expected: %d", CURRENT_CDS_ARCHIVE_VERSION);
|
||||
log_info(cds)(" actual: %d", _header->_version);
|
||||
log_info(cds)(" actual: %d", header()->version());
|
||||
fail_continue("The shared archive file has the wrong version.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_header->_header_size != sz) {
|
||||
if (header()->header_size() != sz) {
|
||||
log_info(cds)("_header_size expected: " SIZE_FORMAT, sz);
|
||||
log_info(cds)(" actual: " SIZE_FORMAT, _header->_header_size);
|
||||
log_info(cds)(" actual: " SIZE_FORMAT, header()->header_size());
|
||||
FileMapInfo::fail_continue("The shared archive file has an incorrect header size.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_header->_jvm_ident[JVM_IDENT_MAX-1] != 0) {
|
||||
const char* actual_ident = header()->jvm_ident();
|
||||
|
||||
if (actual_ident[JVM_IDENT_MAX-1] != 0) {
|
||||
FileMapInfo::fail_continue("JVM version identifier is corrupted.");
|
||||
return false;
|
||||
}
|
||||
|
||||
char header_version[JVM_IDENT_MAX];
|
||||
get_header_version(header_version);
|
||||
if (strncmp(_header->_jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) {
|
||||
log_info(cds)("_jvm_ident expected: %s", header_version);
|
||||
log_info(cds)(" actual: %s", _header->_jvm_ident);
|
||||
char expected_ident[JVM_IDENT_MAX];
|
||||
get_header_version(expected_ident);
|
||||
if (strncmp(actual_ident, expected_ident, JVM_IDENT_MAX-1) != 0) {
|
||||
log_info(cds)("_jvm_ident expected: %s", expected_ident);
|
||||
log_info(cds)(" actual: %s", actual_ident);
|
||||
FileMapInfo::fail_continue("The shared archive file was created by a different"
|
||||
" version or build of HotSpot");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (VerifySharedSpaces) {
|
||||
int expected_crc = _header->compute_crc();
|
||||
if (expected_crc != _header->_crc) {
|
||||
int expected_crc = header()->compute_crc();
|
||||
if (expected_crc != header()->crc()) {
|
||||
log_info(cds)("_crc expected: %d", expected_crc);
|
||||
log_info(cds)(" actual: %d", _header->_crc);
|
||||
log_info(cds)(" actual: %d", header()->crc());
|
||||
FileMapInfo::fail_continue("Header checksum verification failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_file_offset = n + _header->_base_archive_name_size; // accounts for the size of _base_archive_name
|
||||
_file_offset = n + header()->base_archive_name_size(); // accounts for the size of _base_archive_name
|
||||
|
||||
if (is_static) {
|
||||
// just checking the last region is sufficient since the archive is written
|
||||
// in sequential order
|
||||
size_t len = lseek(fd, 0, SEEK_END);
|
||||
CDSFileMapRegion* si = space_at(MetaspaceShared::last_valid_region);
|
||||
FileMapRegion* si = space_at(MetaspaceShared::last_valid_region);
|
||||
// The last space might be empty
|
||||
if (si->_file_offset > len || len - si->_file_offset < si->_used) {
|
||||
if (si->file_offset() > len || len - si->file_offset() < si->used()) {
|
||||
fail_continue("The shared archive file has been truncated.");
|
||||
return false;
|
||||
}
|
||||
|
||||
SharedBaseAddress = _header->_shared_base_address;
|
||||
SharedBaseAddress = header()->shared_base_address();
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1095,20 +1097,41 @@ void FileMapInfo::open_for_write(const char* path) {
|
||||
|
||||
void FileMapInfo::write_header() {
|
||||
char* base_archive_name = NULL;
|
||||
if (_header->_magic == CDS_DYNAMIC_ARCHIVE_MAGIC) {
|
||||
if (header()->magic() == CDS_DYNAMIC_ARCHIVE_MAGIC) {
|
||||
base_archive_name = (char*)Arguments::GetSharedArchivePath();
|
||||
_header->_base_archive_name_size = (int)strlen(base_archive_name) + 1;
|
||||
_header->_base_archive_is_default = FLAG_IS_DEFAULT(SharedArchiveFile);
|
||||
header()->set_base_archive_name_size(strlen(base_archive_name) + 1);
|
||||
header()->set_base_archive_is_default(FLAG_IS_DEFAULT(SharedArchiveFile));
|
||||
}
|
||||
|
||||
assert(is_file_position_aligned(), "must be");
|
||||
write_bytes(_header, _header->_header_size);
|
||||
write_bytes(header(), header()->header_size());
|
||||
if (base_archive_name != NULL) {
|
||||
write_bytes(base_archive_name, (size_t)_header->_base_archive_name_size);
|
||||
write_bytes(base_archive_name, header()->base_archive_name_size());
|
||||
}
|
||||
align_file_position();
|
||||
}
|
||||
|
||||
void FileMapRegion::init(bool is_heap_region, char* base, size_t size, bool read_only,
|
||||
bool allow_exec, int crc) {
|
||||
_is_heap_region = is_heap_region;
|
||||
|
||||
if (is_heap_region) {
|
||||
assert(!DynamicDumpSharedSpaces, "must be");
|
||||
assert((base - (char*)CompressedKlassPointers::base()) % HeapWordSize == 0, "Sanity");
|
||||
if (base != NULL) {
|
||||
_addr._offset = (intx)CompressedOops::encode_not_null((oop)base);
|
||||
} else {
|
||||
_addr._offset = 0;
|
||||
}
|
||||
} else {
|
||||
_addr._base = base;
|
||||
}
|
||||
_used = size;
|
||||
_read_only = read_only;
|
||||
_allow_exec = allow_exec;
|
||||
_crc = crc;
|
||||
}
|
||||
|
||||
// Dump region to file.
|
||||
// This is called twice for each region during archiving, once before
|
||||
// the archive file is open (_file_open is false) and once after.
|
||||
@ -1116,37 +1139,25 @@ void FileMapInfo::write_region(int region, char* base, size_t size,
|
||||
bool read_only, bool allow_exec) {
|
||||
assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "Dump time only");
|
||||
|
||||
CDSFileMapRegion* si = space_at(region);
|
||||
FileMapRegion* si = space_at(region);
|
||||
char* target_base = base;
|
||||
if (DynamicDumpSharedSpaces) {
|
||||
assert(!HeapShared::is_heap_region(region), "dynamic archive doesn't support heap regions");
|
||||
target_base = DynamicArchive::buffer_to_target(base);
|
||||
}
|
||||
|
||||
if (_file_open) {
|
||||
guarantee(si->_file_offset == _file_offset, "file offset mismatch.");
|
||||
guarantee(si->file_offset() == _file_offset, "file offset mismatch.");
|
||||
log_info(cds)("Shared file region %d: " SIZE_FORMAT_HEX_W(08)
|
||||
" bytes, addr " INTPTR_FORMAT " file offset " SIZE_FORMAT_HEX_W(08),
|
||||
region, size, p2i(target_base), _file_offset);
|
||||
} else {
|
||||
si->_file_offset = _file_offset;
|
||||
si->set_file_offset(_file_offset);
|
||||
}
|
||||
|
||||
if (HeapShared::is_heap_region(region)) {
|
||||
assert((target_base - (char*)CompressedKlassPointers::base()) % HeapWordSize == 0, "Sanity");
|
||||
if (target_base != NULL) {
|
||||
si->_addr._offset = (intx)CompressedOops::encode_not_null((oop)target_base);
|
||||
} else {
|
||||
si->_addr._offset = 0;
|
||||
}
|
||||
} else {
|
||||
si->_addr._base = target_base;
|
||||
}
|
||||
si->_used = size;
|
||||
si->_read_only = read_only;
|
||||
si->_allow_exec = allow_exec;
|
||||
int crc = ClassLoader::crc32(0, base, (jint)size);
|
||||
si->init(HeapShared::is_heap_region(region), target_base, size, read_only, allow_exec, crc);
|
||||
|
||||
// Use the current 'base' when computing the CRC value and writing out data
|
||||
si->_crc = ClassLoader::crc32(0, base, (jint)size);
|
||||
if (base != NULL) {
|
||||
write_bytes_aligned(base, size);
|
||||
}
|
||||
@ -1216,8 +1227,8 @@ size_t FileMapInfo::write_archive_heap_regions(GrowableArray<MemRegion> *heap_me
|
||||
}
|
||||
write_region(i, start, size, false, false);
|
||||
if (size > 0) {
|
||||
space_at(i)->_oopmap = oopmaps->at(arr_idx)._oopmap;
|
||||
space_at(i)->_oopmap_size_in_bits = oopmaps->at(arr_idx)._oopmap_size_in_bits;
|
||||
space_at(i)->init_oopmap(oopmaps->at(arr_idx)._oopmap,
|
||||
oopmaps->at(arr_idx)._oopmap_size_in_bits);
|
||||
}
|
||||
}
|
||||
return total_size;
|
||||
@ -1290,20 +1301,20 @@ void FileMapInfo::close() {
|
||||
// Remap the shared readonly space to shared readwrite, private.
|
||||
bool FileMapInfo::remap_shared_readonly_as_readwrite() {
|
||||
int idx = MetaspaceShared::ro;
|
||||
CDSFileMapRegion* si = space_at(idx);
|
||||
if (!si->_read_only) {
|
||||
FileMapRegion* si = space_at(idx);
|
||||
if (!si->read_only()) {
|
||||
// the space is already readwrite so we are done
|
||||
return true;
|
||||
}
|
||||
size_t used = si->_used;
|
||||
size_t used = si->used();
|
||||
size_t size = align_up(used, os::vm_allocation_granularity());
|
||||
if (!open_for_read()) {
|
||||
return false;
|
||||
}
|
||||
char *addr = region_addr(idx);
|
||||
char *base = os::remap_memory(_fd, _full_path, si->_file_offset,
|
||||
char *base = os::remap_memory(_fd, _full_path, si->file_offset(),
|
||||
addr, size, false /* !read_only */,
|
||||
si->_allow_exec);
|
||||
si->allow_exec());
|
||||
close();
|
||||
// These have to be errors because the shared region is now unmapped.
|
||||
if (base == NULL) {
|
||||
@ -1314,7 +1325,7 @@ bool FileMapInfo::remap_shared_readonly_as_readwrite() {
|
||||
log_error(cds)("Unable to remap shared readonly space (errno=%d).", errno);
|
||||
vm_exit(1);
|
||||
}
|
||||
si->_read_only = false;
|
||||
si->set_read_only(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1367,8 +1378,8 @@ char* FileMapInfo::map_regions(int regions[], char* saved_base[], size_t len) {
|
||||
|
||||
char* FileMapInfo::map_region(int i, char** top_ret) {
|
||||
assert(!HeapShared::is_heap_region(i), "sanity");
|
||||
CDSFileMapRegion* si = space_at(i);
|
||||
size_t used = si->_used;
|
||||
FileMapRegion* si = space_at(i);
|
||||
size_t used = si->used();
|
||||
size_t alignment = os::vm_allocation_granularity();
|
||||
size_t size = align_up(used, alignment);
|
||||
char *requested_addr = region_addr(i);
|
||||
@ -1376,19 +1387,19 @@ char* FileMapInfo::map_region(int i, char** top_ret) {
|
||||
#ifdef _WINDOWS
|
||||
// Windows cannot remap read-only shared memory to read-write when required for
|
||||
// RedefineClasses, which is also used by JFR. Always map windows regions as RW.
|
||||
si->_read_only = false;
|
||||
si->set_read_only(false);
|
||||
#else
|
||||
// If a tool agent is in use (debugging enabled), or JFR, we must map the address space RW
|
||||
if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space() ||
|
||||
Arguments::has_jfr_option()) {
|
||||
si->_read_only = false;
|
||||
si->set_read_only(false);
|
||||
}
|
||||
#endif // _WINDOWS
|
||||
|
||||
// map the contents of the CDS archive in this memory
|
||||
char *base = os::map_memory(_fd, _full_path, si->_file_offset,
|
||||
requested_addr, size, si->_read_only,
|
||||
si->_allow_exec);
|
||||
char *base = os::map_memory(_fd, _full_path, si->file_offset(),
|
||||
requested_addr, size, si->read_only(),
|
||||
si->allow_exec());
|
||||
if (base == NULL || base != requested_addr) {
|
||||
fail_continue("Unable to map %s shared space at required address.", shared_region_name[i]);
|
||||
_memory_mapping_failed = true;
|
||||
@ -1420,11 +1431,11 @@ size_t FileMapInfo::read_bytes(void* buffer, size_t count) {
|
||||
return count;
|
||||
}
|
||||
|
||||
address FileMapInfo::decode_start_address(CDSFileMapRegion* spc, bool with_current_oop_encoding_mode) {
|
||||
address FileMapInfo::decode_start_address(FileMapRegion* spc, bool with_current_oop_encoding_mode) {
|
||||
if (with_current_oop_encoding_mode) {
|
||||
return (address)CompressedOops::decode_not_null(offset_of_space(spc));
|
||||
return (address)CompressedOops::decode_not_null(spc->offset());
|
||||
} else {
|
||||
return (address)HeapShared::decode_from_archive(offset_of_space(spc));
|
||||
return (address)HeapShared::decode_from_archive(spc->offset());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1435,7 +1446,7 @@ static int num_open_archive_heap_ranges = 0;
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
bool FileMapInfo::has_heap_regions() {
|
||||
return (_header->_space[MetaspaceShared::first_closed_archive_heap_region]._used > 0);
|
||||
return (space_at(MetaspaceShared::first_closed_archive_heap_region)->used() > 0);
|
||||
}
|
||||
|
||||
// Returns the address range of the archived heap regions computed using the
|
||||
@ -1449,8 +1460,8 @@ MemRegion FileMapInfo::get_heap_regions_range_with_current_oop_encoding_mode() {
|
||||
for (int i = MetaspaceShared::first_closed_archive_heap_region;
|
||||
i <= MetaspaceShared::last_valid_region;
|
||||
i++) {
|
||||
CDSFileMapRegion* si = space_at(i);
|
||||
size_t size = si->_used;
|
||||
FileMapRegion* si = space_at(i);
|
||||
size_t size = si->used();
|
||||
if (size > 0) {
|
||||
address s = start_address_as_decoded_with_current_oop_encoding_mode(si);
|
||||
address e = s + size;
|
||||
@ -1546,7 +1557,7 @@ void FileMapInfo::map_heap_regions_impl() {
|
||||
// At run time, they may not be inside the heap, so we move them so
|
||||
// that they are now near the top of the runtime time. This can be done by
|
||||
// the simple math of adding the delta as shown above.
|
||||
address dumptime_heap_end = (address)_header->_heap_end;
|
||||
address dumptime_heap_end = header()->heap_end();
|
||||
address runtime_heap_end = (address)CompressedOops::end();
|
||||
delta = runtime_heap_end - dumptime_heap_end;
|
||||
}
|
||||
@ -1554,7 +1565,7 @@ void FileMapInfo::map_heap_regions_impl() {
|
||||
log_info(cds)("CDS heap data relocation delta = " INTX_FORMAT " bytes", delta);
|
||||
HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift());
|
||||
|
||||
CDSFileMapRegion* si = space_at(MetaspaceShared::first_closed_archive_heap_region);
|
||||
FileMapRegion* si = space_at(MetaspaceShared::first_closed_archive_heap_region);
|
||||
address relocated_closed_heap_region_bottom = start_address_as_decoded_from_archive(si);
|
||||
if (!is_aligned(relocated_closed_heap_region_bottom, HeapRegion::GrainBytes)) {
|
||||
// Align the bottom of the closed archive heap regions at G1 region boundary.
|
||||
@ -1609,13 +1620,13 @@ void FileMapInfo::map_heap_regions() {
|
||||
bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first,
|
||||
int max, int* num, bool is_open_archive) {
|
||||
MemRegion * regions = new MemRegion[max];
|
||||
CDSFileMapRegion* si;
|
||||
FileMapRegion* si;
|
||||
int region_num = 0;
|
||||
|
||||
for (int i = first;
|
||||
i < first + max; i++) {
|
||||
si = space_at(i);
|
||||
size_t size = si->_used;
|
||||
size_t size = si->used();
|
||||
if (size > 0) {
|
||||
HeapWord* start = (HeapWord*)start_address_as_decoded_from_archive(si);
|
||||
regions[region_num] = MemRegion(start, size / HeapWordSize);
|
||||
@ -1648,9 +1659,9 @@ bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first,
|
||||
for (int i = 0; i < region_num; i++) {
|
||||
si = space_at(first + i);
|
||||
char* addr = (char*)regions[i].start();
|
||||
char* base = os::map_memory(_fd, _full_path, si->_file_offset,
|
||||
addr, regions[i].byte_size(), si->_read_only,
|
||||
si->_allow_exec);
|
||||
char* base = os::map_memory(_fd, _full_path, si->file_offset(),
|
||||
addr, regions[i].byte_size(), si->read_only(),
|
||||
si->allow_exec());
|
||||
if (base == NULL || base != addr) {
|
||||
// dealloc the regions from java heap
|
||||
dealloc_archive_heap_regions(regions, region_num, is_open_archive);
|
||||
@ -1660,7 +1671,7 @@ bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (VerifySharedSpaces && !region_crc_check(addr, regions[i].byte_size(), si->_crc)) {
|
||||
if (VerifySharedSpaces && !region_crc_check(addr, regions[i].byte_size(), si->crc())) {
|
||||
// dealloc the regions from java heap
|
||||
dealloc_archive_heap_regions(regions, region_num, is_open_archive);
|
||||
log_info(cds)("UseSharedSpaces: mapped heap regions are corrupt");
|
||||
@ -1691,9 +1702,9 @@ void FileMapInfo::patch_archived_heap_embedded_pointers() {
|
||||
void FileMapInfo::patch_archived_heap_embedded_pointers(MemRegion* ranges, int num_ranges,
|
||||
int first_region_idx) {
|
||||
for (int i=0; i<num_ranges; i++) {
|
||||
CDSFileMapRegion* si = space_at(i + first_region_idx);
|
||||
HeapShared::patch_archived_heap_embedded_pointers(ranges[i], (address)si->_oopmap,
|
||||
si->_oopmap_size_in_bits);
|
||||
FileMapRegion* si = space_at(i + first_region_idx);
|
||||
HeapShared::patch_archived_heap_embedded_pointers(ranges[i], (address)si->oopmap(),
|
||||
si->oopmap_size_in_bits());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1737,14 +1748,13 @@ bool FileMapInfo::region_crc_check(char* buf, size_t size, int expected_crc) {
|
||||
|
||||
bool FileMapInfo::verify_region_checksum(int i) {
|
||||
assert(VerifySharedSpaces, "sanity");
|
||||
|
||||
size_t sz = space_at(i)->_used;
|
||||
size_t sz = space_at(i)->used();
|
||||
|
||||
if (sz == 0) {
|
||||
return true; // no data
|
||||
} else {
|
||||
return region_crc_check(region_addr(i), sz, space_at(i)->crc());
|
||||
}
|
||||
|
||||
return region_crc_check(region_addr(i), sz, space_at(i)->_crc);
|
||||
}
|
||||
|
||||
void FileMapInfo::unmap_regions(int regions[], char* saved_base[], size_t len) {
|
||||
@ -1759,8 +1769,8 @@ void FileMapInfo::unmap_regions(int regions[], char* saved_base[], size_t len) {
|
||||
|
||||
void FileMapInfo::unmap_region(int i) {
|
||||
assert(!HeapShared::is_heap_region(i), "sanity");
|
||||
CDSFileMapRegion* si = space_at(i);
|
||||
size_t used = si->_used;
|
||||
FileMapRegion* si = space_at(i);
|
||||
size_t used = si->used();
|
||||
size_t size = align_up(used, os::vm_allocation_granularity());
|
||||
|
||||
if (used == 0) {
|
||||
@ -1827,13 +1837,13 @@ bool FileMapInfo::initialize(bool is_static) {
|
||||
}
|
||||
|
||||
char* FileMapInfo::region_addr(int idx) {
|
||||
CDSFileMapRegion* si = space_at(idx);
|
||||
FileMapRegion* si = space_at(idx);
|
||||
if (HeapShared::is_heap_region(idx)) {
|
||||
assert(DumpSharedSpaces, "The following doesn't work at runtime");
|
||||
return si->_used > 0 ?
|
||||
return si->used() > 0 ?
|
||||
(char*)start_address_as_decoded_with_current_oop_encoding_mode(si) : NULL;
|
||||
} else {
|
||||
return si->_addr._base;
|
||||
return si->base();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1902,7 +1912,7 @@ bool FileMapHeader::validate() {
|
||||
}
|
||||
|
||||
bool FileMapInfo::validate_header(bool is_static) {
|
||||
return _header->validate();
|
||||
return header()->validate();
|
||||
}
|
||||
|
||||
// Check if a given address is within one of the shared regions
|
||||
@ -1912,7 +1922,7 @@ bool FileMapInfo::is_in_shared_region(const void* p, int idx) {
|
||||
idx == MetaspaceShared::mc ||
|
||||
idx == MetaspaceShared::md, "invalid region index");
|
||||
char* base = region_addr(idx);
|
||||
if (p >= base && p < base + space_at(idx)->_used) {
|
||||
if (p >= base && p < base + space_at(idx)->used()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1930,7 +1940,7 @@ void FileMapInfo::stop_sharing_and_unmap(const char* msg) {
|
||||
char *addr = map_info->region_addr(i);
|
||||
if (addr != NULL) {
|
||||
map_info->unmap_region(i);
|
||||
map_info->space_at(i)->_addr._base = NULL;
|
||||
map_info->space_at(i)->mark_invalid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,6 @@ class SharedClassPathEntry {
|
||||
|
||||
void set_name(const char* name, TRAPS);
|
||||
|
||||
protected:
|
||||
u1 _type;
|
||||
bool _from_class_path_attr;
|
||||
time_t _timestamp; // jar timestamp, 0 if is directory, modules image or other
|
||||
@ -122,24 +121,70 @@ public:
|
||||
}
|
||||
Array<u8>* table() {return _table;}
|
||||
void set_table(Array<u8>* table) {_table = table;}
|
||||
|
||||
};
|
||||
|
||||
struct FileMapHeader : public CDSFileMapHeaderBase {
|
||||
|
||||
class FileMapRegion: private CDSFileMapRegion {
|
||||
void assert_is_heap_region() const {
|
||||
assert(_is_heap_region, "must be heap region");
|
||||
}
|
||||
void assert_is_not_heap_region() const {
|
||||
assert(!_is_heap_region, "must not be heap region");
|
||||
}
|
||||
|
||||
public:
|
||||
static FileMapRegion* cast(CDSFileMapRegion* p) {
|
||||
return (FileMapRegion*)p;
|
||||
}
|
||||
|
||||
// Accessors
|
||||
int crc() const { return _crc; }
|
||||
size_t file_offset() const { return _file_offset; }
|
||||
char* base() const { assert_is_not_heap_region(); return _addr._base; }
|
||||
narrowOop offset() const { assert_is_heap_region(); return (narrowOop)(_addr._offset); }
|
||||
size_t used() const { return _used; }
|
||||
bool read_only() const { return _read_only != 0; }
|
||||
bool allow_exec() const { return _allow_exec != 0; }
|
||||
void* oopmap() const { return _oopmap; }
|
||||
size_t oopmap_size_in_bits() const { return _oopmap_size_in_bits; }
|
||||
|
||||
void set_file_offset(size_t s) { _file_offset = s; }
|
||||
void set_read_only(bool v) { _read_only = v; }
|
||||
void mark_invalid() { _addr._base = NULL; }
|
||||
|
||||
void init(bool is_heap_region, char* base, size_t size, bool read_only,
|
||||
bool allow_exec, int crc);
|
||||
|
||||
void init_oopmap(void* map, size_t size_in_bits) {
|
||||
_oopmap = map;
|
||||
_oopmap_size_in_bits = size_in_bits;
|
||||
}
|
||||
};
|
||||
|
||||
class FileMapHeader: private CDSFileMapHeaderBase {
|
||||
friend class CDSOffsets;
|
||||
friend class VMStructs;
|
||||
|
||||
size_t _header_size;
|
||||
|
||||
// The following fields record the states of the VM during dump time.
|
||||
// They are compared with the runtime states to see if the archive
|
||||
// can be used.
|
||||
size_t _alignment; // how shared archive should be aligned
|
||||
int _obj_alignment; // value of ObjectAlignmentInBytes
|
||||
address _narrow_oop_base; // compressed oop encoding base
|
||||
int _narrow_oop_shift; // compressed oop encoding shift
|
||||
bool _compact_strings; // value of CompactStrings
|
||||
bool _compact_strings; // value of CompactStrings
|
||||
uintx _max_heap_size; // java max heap size during dumping
|
||||
CompressedOops::Mode _narrow_oop_mode; // compressed oop encoding mode
|
||||
int _narrow_klass_shift; // save narrow klass base and shift
|
||||
address _narrow_klass_base;
|
||||
|
||||
|
||||
char* _misc_data_patching_start;
|
||||
char* _read_only_tables_start;
|
||||
address _cds_i2i_entry_code_buffers;
|
||||
size_t _cds_i2i_entry_code_buffers_size;
|
||||
address _i2i_entry_code_buffers;
|
||||
size_t _i2i_entry_code_buffers_size;
|
||||
size_t _core_spaces_size; // number of bytes allocated by the core spaces
|
||||
// (mc, md, ro, rw and od).
|
||||
address _heap_end; // heap end at dump time.
|
||||
@ -148,10 +193,10 @@ struct FileMapHeader : public CDSFileMapHeaderBase {
|
||||
// The following fields are all sanity checks for whether this archive
|
||||
// will function correctly with this JVM and the bootclasspath it's
|
||||
// invoked with.
|
||||
char _jvm_ident[JVM_IDENT_MAX]; // identifier for jvm
|
||||
char _jvm_ident[JVM_IDENT_MAX]; // identifier string of the jvm that created this dump
|
||||
|
||||
// size of the base archive name including NULL terminator
|
||||
int _base_archive_name_size;
|
||||
size_t _base_archive_name_size;
|
||||
|
||||
// The following is a table of all the boot/app/module path entries that were used
|
||||
// during dumping. At run time, we validate these entries according to their
|
||||
@ -171,36 +216,99 @@ struct FileMapHeader : public CDSFileMapHeaderBase {
|
||||
size_t _shared_base_address; // SharedBaseAddress used at dump time
|
||||
bool _allow_archiving_with_java_agent; // setting of the AllowArchivingWithJavaAgent option
|
||||
|
||||
void set_has_platform_or_app_classes(bool v) {
|
||||
_has_platform_or_app_classes = v;
|
||||
public:
|
||||
// Accessors -- fields declared in CDSFileMapHeaderBase
|
||||
unsigned int magic() const {return _magic;}
|
||||
int crc() const { return _crc; }
|
||||
int version() const { return _version; }
|
||||
|
||||
void set_crc(int crc_value) { _crc = crc_value; }
|
||||
void set_version(int v) { _version = v; }
|
||||
|
||||
// Accessors -- fields declared in FileMapHeader
|
||||
|
||||
size_t header_size() const { return _header_size; }
|
||||
size_t alignment() const { return _alignment; }
|
||||
int obj_alignment() const { return _obj_alignment; }
|
||||
address narrow_oop_base() const { return _narrow_oop_base; }
|
||||
int narrow_oop_shift() const { return _narrow_oop_shift; }
|
||||
bool compact_strings() const { return _compact_strings; }
|
||||
uintx max_heap_size() const { return _max_heap_size; }
|
||||
CompressedOops::Mode narrow_oop_mode() const { return _narrow_oop_mode; }
|
||||
int narrow_klass_shift() const { return _narrow_klass_shift; }
|
||||
address narrow_klass_base() const { return _narrow_klass_base; }
|
||||
char* misc_data_patching_start() const { return _misc_data_patching_start; }
|
||||
char* read_only_tables_start() const { return _read_only_tables_start; }
|
||||
address i2i_entry_code_buffers() const { return _i2i_entry_code_buffers; }
|
||||
size_t i2i_entry_code_buffers_size() const { return _i2i_entry_code_buffers_size; }
|
||||
size_t core_spaces_size() const { return _core_spaces_size; }
|
||||
address heap_end() const { return _heap_end; }
|
||||
bool base_archive_is_default() const { return _base_archive_is_default; }
|
||||
const char* jvm_ident() const { return _jvm_ident; }
|
||||
size_t base_archive_name_size() const { return _base_archive_name_size; }
|
||||
size_t shared_base_address() const { return _shared_base_address; }
|
||||
bool has_platform_or_app_classes() const { return _has_platform_or_app_classes; }
|
||||
SharedPathTable shared_path_table() const { return _shared_path_table; }
|
||||
|
||||
// FIXME: These should really return int
|
||||
jshort max_used_path_index() const { return _max_used_path_index; }
|
||||
jshort app_module_paths_start_index() const { return _app_module_paths_start_index; }
|
||||
jshort app_class_paths_start_index() const { return _app_class_paths_start_index; }
|
||||
jshort num_module_paths() const { return _num_module_paths; }
|
||||
|
||||
void set_core_spaces_size(size_t s) { _core_spaces_size = s; }
|
||||
void set_has_platform_or_app_classes(bool v) { _has_platform_or_app_classes = v; }
|
||||
void set_misc_data_patching_start(char* p) { _misc_data_patching_start = p; }
|
||||
void set_read_only_tables_start(char* p) { _read_only_tables_start = p; }
|
||||
void set_base_archive_name_size(size_t s) { _base_archive_name_size = s; }
|
||||
void set_base_archive_is_default(bool b) { _base_archive_is_default = b; }
|
||||
void set_header_size(size_t s) { _header_size = s; }
|
||||
|
||||
void set_i2i_entry_code_buffers(address p, size_t s) {
|
||||
_i2i_entry_code_buffers = p;
|
||||
_i2i_entry_code_buffers_size = s;
|
||||
}
|
||||
|
||||
void relocate_shared_path_table(Array<u8>* t) {
|
||||
assert(DynamicDumpSharedSpaces, "only");
|
||||
_shared_path_table.set_table(t);
|
||||
}
|
||||
|
||||
void shared_path_table_metaspace_pointers_do(MetaspaceClosure* it) {
|
||||
assert(DynamicDumpSharedSpaces, "only");
|
||||
_shared_path_table.metaspace_pointers_do(it);
|
||||
}
|
||||
bool has_platform_or_app_classes() { return _has_platform_or_app_classes; }
|
||||
jshort max_used_path_index() { return _max_used_path_index; }
|
||||
jshort app_module_paths_start_index() { return _app_module_paths_start_index; }
|
||||
|
||||
bool validate();
|
||||
int compute_crc();
|
||||
|
||||
CDSFileMapRegion* space_at(int i) {
|
||||
assert(i >= 0 && i < NUM_CDS_REGIONS, "invalid region");
|
||||
return &_space[i];
|
||||
FileMapRegion* space_at(int i) {
|
||||
assert(is_valid_region(i), "invalid region");
|
||||
return FileMapRegion::cast(&_space[i]);
|
||||
}
|
||||
public:
|
||||
|
||||
void populate(FileMapInfo* info, size_t alignment);
|
||||
|
||||
static bool is_valid_region(int region) {
|
||||
return (0 <= region && region < NUM_CDS_REGIONS);
|
||||
}
|
||||
};
|
||||
|
||||
class FileMapInfo : public CHeapObj<mtInternal> {
|
||||
private:
|
||||
friend class ManifestStream;
|
||||
friend class VMStructs;
|
||||
friend struct FileMapHeader;
|
||||
friend class CDSOffsets;
|
||||
friend class FileMapHeader;
|
||||
|
||||
bool _is_static;
|
||||
bool _file_open;
|
||||
int _fd;
|
||||
size_t _file_offset;
|
||||
bool _is_static;
|
||||
bool _file_open;
|
||||
int _fd;
|
||||
size_t _file_offset;
|
||||
const char* _full_path;
|
||||
const char* _base_archive_name;
|
||||
FileMapHeader* _header;
|
||||
|
||||
private:
|
||||
// TODO: Probably change the following to be non-static
|
||||
static SharedPathTable _shared_path_table;
|
||||
static bool _validating_shared_path_table;
|
||||
@ -209,76 +317,75 @@ private:
|
||||
// mapped. This structure gets written to a file. It is not a class, so
|
||||
// that the compilers don't add any compiler-private data to it.
|
||||
|
||||
public:
|
||||
struct FileMapHeaderBase : public CHeapObj<mtClass> {
|
||||
// Need to put something here. Otherwise, in product build, because CHeapObj has no virtual
|
||||
// methods, we would get sizeof(FileMapHeaderBase) == 1 with gcc.
|
||||
intx _dummy;
|
||||
};
|
||||
|
||||
|
||||
FileMapHeader * _header;
|
||||
|
||||
const char* _full_path;
|
||||
char* _base_archive_name;
|
||||
|
||||
static FileMapInfo* _current_info;
|
||||
static FileMapInfo* _dynamic_archive_info;
|
||||
static bool _heap_pointers_need_patching;
|
||||
static bool _memory_mapping_failed;
|
||||
static GrowableArray<const char*>* _non_existent_class_paths;
|
||||
|
||||
FileMapHeader *header() const { return _header; }
|
||||
|
||||
public:
|
||||
static bool get_base_archive_name_from_header(const char* archive_name,
|
||||
int* size, char** base_archive_name);
|
||||
static bool check_archive(const char* archive_name, bool is_static);
|
||||
void restore_shared_path_table();
|
||||
bool init_from_file(int fd, bool is_static);
|
||||
bool init_from_file(int fd, bool is_static);
|
||||
static void metaspace_pointers_do(MetaspaceClosure* it);
|
||||
|
||||
void log_paths(const char* msg, int start_idx, int end_idx);
|
||||
|
||||
public:
|
||||
FileMapInfo(bool is_static);
|
||||
~FileMapInfo();
|
||||
|
||||
int compute_header_crc() { return _header->compute_crc(); }
|
||||
void set_header_crc(int crc) { _header->_crc = crc; }
|
||||
int space_crc(int i) { return space_at(i)->_crc; }
|
||||
// Accessors
|
||||
int compute_header_crc() const { return header()->compute_crc(); }
|
||||
void set_header_crc(int crc) { header()->set_crc(crc); }
|
||||
int space_crc(int i) const { return space_at(i)->crc(); }
|
||||
void populate_header(size_t alignment);
|
||||
bool validate_header(bool is_static);
|
||||
void invalidate();
|
||||
int crc() { return _header->_crc; }
|
||||
int version() { return _header->_version; }
|
||||
size_t alignment() { return _header->_alignment; }
|
||||
CompressedOops::Mode narrow_oop_mode() { return _header->_narrow_oop_mode; }
|
||||
address narrow_oop_base() const { return _header->_narrow_oop_base; }
|
||||
int narrow_oop_shift() const { return _header->_narrow_oop_shift; }
|
||||
uintx max_heap_size() const { return _header->_max_heap_size; }
|
||||
address narrow_klass_base() const { return _header->_narrow_klass_base; }
|
||||
int narrow_klass_shift() const { return _header->_narrow_klass_shift; }
|
||||
struct FileMapHeader* header() { return _header; }
|
||||
char* misc_data_patching_start() { return _header->_misc_data_patching_start; }
|
||||
void set_misc_data_patching_start(char* p) { _header->_misc_data_patching_start = p; }
|
||||
char* read_only_tables_start() { return _header->_read_only_tables_start; }
|
||||
void set_read_only_tables_start(char* p) { _header->_read_only_tables_start = p; }
|
||||
int crc() const { return header()->crc(); }
|
||||
int version() const { return header()->version(); }
|
||||
size_t alignment() const { return header()->alignment(); }
|
||||
address narrow_oop_base() const { return header()->narrow_oop_base(); }
|
||||
int narrow_oop_shift() const { return header()->narrow_oop_shift(); }
|
||||
uintx max_heap_size() const { return header()->max_heap_size(); }
|
||||
address narrow_klass_base() const { return header()->narrow_klass_base(); }
|
||||
int narrow_klass_shift() const { return header()->narrow_klass_shift(); }
|
||||
|
||||
CompressedOops::Mode narrow_oop_mode() const { return header()->narrow_oop_mode(); }
|
||||
jshort app_module_paths_start_index() const { return header()->app_module_paths_start_index(); }
|
||||
jshort app_class_paths_start_index() const { return header()->app_class_paths_start_index(); }
|
||||
|
||||
char* misc_data_patching_start() const { return header()->misc_data_patching_start(); }
|
||||
void set_misc_data_patching_start(char* p) const { header()->set_misc_data_patching_start(p); }
|
||||
char* read_only_tables_start() const { return header()->read_only_tables_start(); }
|
||||
void set_read_only_tables_start(char* p) const { header()->set_read_only_tables_start(p); }
|
||||
|
||||
bool is_file_position_aligned() const;
|
||||
void align_file_position();
|
||||
|
||||
address cds_i2i_entry_code_buffers() {
|
||||
return _header->_cds_i2i_entry_code_buffers;
|
||||
address i2i_entry_code_buffers() const { return header()->i2i_entry_code_buffers(); }
|
||||
size_t i2i_entry_code_buffers_size() const { return header()->i2i_entry_code_buffers_size(); }
|
||||
void set_i2i_entry_code_buffers(address addr, size_t s) const {
|
||||
header()->set_i2i_entry_code_buffers(addr, s);
|
||||
}
|
||||
void set_cds_i2i_entry_code_buffers(address addr) {
|
||||
_header->_cds_i2i_entry_code_buffers = addr;
|
||||
|
||||
void set_core_spaces_size(size_t s) const { header()->set_core_spaces_size(s); }
|
||||
size_t core_spaces_size() const { return header()->core_spaces_size(); }
|
||||
|
||||
class DynamicArchiveHeader* dynamic_header() const {
|
||||
assert(!_is_static, "must be");
|
||||
return (DynamicArchiveHeader*)header();
|
||||
}
|
||||
size_t cds_i2i_entry_code_buffers_size() {
|
||||
return _header->_cds_i2i_entry_code_buffers_size;
|
||||
|
||||
void set_has_platform_or_app_classes(bool v) {
|
||||
header()->set_has_platform_or_app_classes(v);
|
||||
}
|
||||
void set_cds_i2i_entry_code_buffers_size(size_t s) {
|
||||
_header->_cds_i2i_entry_code_buffers_size = s;
|
||||
bool has_platform_or_app_classes() const {
|
||||
return header()->has_platform_or_app_classes();
|
||||
}
|
||||
void set_core_spaces_size(size_t s) { _header->_core_spaces_size = s; }
|
||||
size_t core_spaces_size() { return _header->_core_spaces_size; }
|
||||
|
||||
static FileMapInfo* current_info() {
|
||||
CDS_ONLY(return _current_info;)
|
||||
@ -385,25 +492,21 @@ public:
|
||||
bool region_crc_check(char* buf, size_t size, int expected_crc) NOT_CDS_RETURN_(false);
|
||||
void dealloc_archive_heap_regions(MemRegion* regions, int num, bool is_open) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
CDSFileMapRegion* space_at(int i) {
|
||||
return _header->space_at(i);
|
||||
}
|
||||
|
||||
narrowOop offset_of_space(CDSFileMapRegion* spc) {
|
||||
return (narrowOop)(spc->_addr._offset);
|
||||
FileMapRegion* space_at(int i) const {
|
||||
return header()->space_at(i);
|
||||
}
|
||||
|
||||
// The starting address of spc, as calculated with CompressedOop::decode_non_null()
|
||||
address start_address_as_decoded_with_current_oop_encoding_mode(CDSFileMapRegion* spc) {
|
||||
address start_address_as_decoded_with_current_oop_encoding_mode(FileMapRegion* spc) {
|
||||
return decode_start_address(spc, true);
|
||||
}
|
||||
|
||||
// The starting address of spc, as calculated with HeapShared::decode_from_archive()
|
||||
address start_address_as_decoded_from_archive(CDSFileMapRegion* spc) {
|
||||
address start_address_as_decoded_from_archive(FileMapRegion* spc) {
|
||||
return decode_start_address(spc, false);
|
||||
}
|
||||
|
||||
address decode_start_address(CDSFileMapRegion* spc, bool with_current_oop_encoding_mode);
|
||||
address decode_start_address(FileMapRegion* spc, bool with_current_oop_encoding_mode);
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
static ClassPathEntry** _classpath_entries_for_jvmti;
|
||||
|
@ -80,8 +80,8 @@ MetaspaceSharedStats MetaspaceShared::_stats;
|
||||
bool MetaspaceShared::_has_error_classes;
|
||||
bool MetaspaceShared::_archive_loading_failed = false;
|
||||
bool MetaspaceShared::_remapped_readwrite = false;
|
||||
address MetaspaceShared::_cds_i2i_entry_code_buffers = NULL;
|
||||
size_t MetaspaceShared::_cds_i2i_entry_code_buffers_size = 0;
|
||||
address MetaspaceShared::_i2i_entry_code_buffers = NULL;
|
||||
size_t MetaspaceShared::_i2i_entry_code_buffers_size = 0;
|
||||
size_t MetaspaceShared::_core_spaces_size = 0;
|
||||
void* MetaspaceShared::_shared_metaspace_static_top = NULL;
|
||||
|
||||
@ -356,14 +356,14 @@ void MetaspaceShared::post_initialize(TRAPS) {
|
||||
if (size > 0) {
|
||||
SystemDictionaryShared::allocate_shared_data_arrays(size, THREAD);
|
||||
if (!DynamicDumpSharedSpaces) {
|
||||
FileMapHeader* header;
|
||||
FileMapInfo* info;
|
||||
if (FileMapInfo::dynamic_info() == NULL) {
|
||||
header = FileMapInfo::current_info()->header();
|
||||
info = FileMapInfo::current_info();
|
||||
} else {
|
||||
header = FileMapInfo::dynamic_info()->header();
|
||||
info = FileMapInfo::dynamic_info();
|
||||
}
|
||||
ClassLoaderExt::init_paths_start_index(header->_app_class_paths_start_index);
|
||||
ClassLoaderExt::init_app_module_paths_start_index(header->_app_module_paths_start_index);
|
||||
ClassLoaderExt::init_paths_start_index(info->app_class_paths_start_index());
|
||||
ClassLoaderExt::init_app_module_paths_start_index(info->app_module_paths_start_index());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -492,20 +492,20 @@ void MetaspaceShared::serialize(SerializeClosure* soc) {
|
||||
soc->do_tag(666);
|
||||
}
|
||||
|
||||
address MetaspaceShared::cds_i2i_entry_code_buffers(size_t total_size) {
|
||||
address MetaspaceShared::i2i_entry_code_buffers(size_t total_size) {
|
||||
if (DumpSharedSpaces) {
|
||||
if (_cds_i2i_entry_code_buffers == NULL) {
|
||||
_cds_i2i_entry_code_buffers = (address)misc_code_space_alloc(total_size);
|
||||
_cds_i2i_entry_code_buffers_size = total_size;
|
||||
if (_i2i_entry_code_buffers == NULL) {
|
||||
_i2i_entry_code_buffers = (address)misc_code_space_alloc(total_size);
|
||||
_i2i_entry_code_buffers_size = total_size;
|
||||
}
|
||||
} else if (UseSharedSpaces) {
|
||||
assert(_cds_i2i_entry_code_buffers != NULL, "must already been initialized");
|
||||
assert(_i2i_entry_code_buffers != NULL, "must already been initialized");
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert(_cds_i2i_entry_code_buffers_size == total_size, "must not change");
|
||||
return _cds_i2i_entry_code_buffers;
|
||||
assert(_i2i_entry_code_buffers_size == total_size, "must not change");
|
||||
return _i2i_entry_code_buffers;
|
||||
}
|
||||
|
||||
uintx MetaspaceShared::object_delta_uintx(void* obj) {
|
||||
@ -1545,8 +1545,8 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||
mapinfo->populate_header(os::vm_allocation_granularity());
|
||||
mapinfo->set_read_only_tables_start(read_only_tables_start);
|
||||
mapinfo->set_misc_data_patching_start(vtbl_list);
|
||||
mapinfo->set_cds_i2i_entry_code_buffers(MetaspaceShared::cds_i2i_entry_code_buffers());
|
||||
mapinfo->set_cds_i2i_entry_code_buffers_size(MetaspaceShared::cds_i2i_entry_code_buffers_size());
|
||||
mapinfo->set_i2i_entry_code_buffers(MetaspaceShared::i2i_entry_code_buffers(),
|
||||
MetaspaceShared::i2i_entry_code_buffers_size());
|
||||
mapinfo->set_core_spaces_size(core_spaces_size);
|
||||
|
||||
for (int pass=1; pass<=2; pass++) {
|
||||
@ -2043,8 +2043,8 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
|
||||
|
||||
void MetaspaceShared::initialize_shared_spaces() {
|
||||
FileMapInfo *mapinfo = FileMapInfo::current_info();
|
||||
_cds_i2i_entry_code_buffers = mapinfo->cds_i2i_entry_code_buffers();
|
||||
_cds_i2i_entry_code_buffers_size = mapinfo->cds_i2i_entry_code_buffers_size();
|
||||
_i2i_entry_code_buffers = mapinfo->i2i_entry_code_buffers();
|
||||
_i2i_entry_code_buffers_size = mapinfo->i2i_entry_code_buffers_size();
|
||||
// _core_spaces_size is loaded from the shared archive immediatelly after mapping
|
||||
assert(_core_spaces_size == mapinfo->core_spaces_size(), "sanity");
|
||||
char* buffer = mapinfo->misc_data_patching_start();
|
||||
|
@ -183,8 +183,8 @@ class MetaspaceShared : AllStatic {
|
||||
static bool _has_error_classes;
|
||||
static bool _archive_loading_failed;
|
||||
static bool _remapped_readwrite;
|
||||
static address _cds_i2i_entry_code_buffers;
|
||||
static size_t _cds_i2i_entry_code_buffers_size;
|
||||
static address _i2i_entry_code_buffers;
|
||||
static size_t _i2i_entry_code_buffers_size;
|
||||
static size_t _core_spaces_size;
|
||||
static void* _shared_metaspace_static_top;
|
||||
public:
|
||||
@ -332,13 +332,13 @@ class MetaspaceShared : AllStatic {
|
||||
return align_up(byte_size, BytesPerWord);
|
||||
}
|
||||
|
||||
static address cds_i2i_entry_code_buffers(size_t total_size);
|
||||
static address i2i_entry_code_buffers(size_t total_size);
|
||||
|
||||
static address cds_i2i_entry_code_buffers() {
|
||||
return _cds_i2i_entry_code_buffers;
|
||||
static address i2i_entry_code_buffers() {
|
||||
return _i2i_entry_code_buffers;
|
||||
}
|
||||
static size_t cds_i2i_entry_code_buffers_size() {
|
||||
return _cds_i2i_entry_code_buffers_size;
|
||||
static size_t i2i_entry_code_buffers_size() {
|
||||
return _i2i_entry_code_buffers_size;
|
||||
}
|
||||
static void relocate_klass_ptr(oop o);
|
||||
|
||||
|
@ -54,7 +54,7 @@ CDSOffsets* CDSOffsets::_all = NULL;
|
||||
ADD_NEXT(_all, "CDSFileMapRegion::_crc", offset_of(CDSFileMapRegion, _crc)); \
|
||||
ADD_NEXT(_all, "CDSFileMapRegion::_used", offset_of(CDSFileMapRegion, _used)); \
|
||||
ADD_NEXT(_all, "file_header_size", sizeof(FileMapHeader)); \
|
||||
ADD_NEXT(_all, "DynamicArchiveHeader::_base_archive_crc", offset_of(DynamicArchiveHeader, _base_archive_crc)); \
|
||||
ADD_NEXT(_all, "DynamicArchiveHeader::_base_region_crc", offset_of(DynamicArchiveHeader, _base_region_crc)); \
|
||||
ADD_NEXT(_all, "CDSFileMapRegion_size", sizeof(CDSFileMapRegion));
|
||||
|
||||
int CDSOffsets::find_offset(const char* name) {
|
||||
|
@ -114,7 +114,7 @@ public class ArchiveConsistency extends DynamicArchiveTestBase {
|
||||
bbuf.put((byte)0);
|
||||
}
|
||||
|
||||
int baseArchiveCRCOffset = wb.getOffsetForName("DynamicArchiveHeader::_base_archive_crc");
|
||||
int baseArchiveCRCOffset = wb.getOffsetForName("DynamicArchiveHeader::_base_region_crc");
|
||||
int crc = 0;
|
||||
System.out.printf("%-12s%-12s\n", "Space name", "CRC");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user