mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8243506: SharedBaseAddress is ignored by -Xshare:dump
Reviewed-by: stuefe, ccheung
This commit is contained in:
parent
b5775c831d
commit
f39a71cafe
10 changed files with 199 additions and 49 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -31,6 +31,7 @@
|
||||||
#include "memory/heapShared.inline.hpp"
|
#include "memory/heapShared.inline.hpp"
|
||||||
#include "memory/metadataFactory.hpp"
|
#include "memory/metadataFactory.hpp"
|
||||||
#include "memory/metaspaceShared.hpp"
|
#include "memory/metaspaceShared.hpp"
|
||||||
|
#include "runtime/globals.hpp"
|
||||||
#include "runtime/vmThread.hpp"
|
#include "runtime/vmThread.hpp"
|
||||||
#include "utilities/numberSeq.hpp"
|
#include "utilities/numberSeq.hpp"
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -212,11 +213,13 @@ size_t SimpleCompactHashtable::calculate_header_size() {
|
||||||
void SimpleCompactHashtable::serialize_header(SerializeClosure* soc) {
|
void SimpleCompactHashtable::serialize_header(SerializeClosure* soc) {
|
||||||
// NOTE: if you change this function, you MUST change the number 5 in
|
// NOTE: if you change this function, you MUST change the number 5 in
|
||||||
// calculate_header_size() accordingly.
|
// calculate_header_size() accordingly.
|
||||||
soc->do_ptr((void**)&_base_address);
|
|
||||||
soc->do_u4(&_entry_count);
|
soc->do_u4(&_entry_count);
|
||||||
soc->do_u4(&_bucket_count);
|
soc->do_u4(&_bucket_count);
|
||||||
soc->do_ptr((void**)&_buckets);
|
soc->do_ptr((void**)&_buckets);
|
||||||
soc->do_ptr((void**)&_entries);
|
soc->do_ptr((void**)&_entries);
|
||||||
|
if (soc->reading()) {
|
||||||
|
_base_address = (address)SharedBaseAddress;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // INCLUDE_CDS
|
#endif // INCLUDE_CDS
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -58,6 +58,12 @@ void ArchivePtrMarker::mark_pointer(address* ptr_loc) {
|
||||||
|
|
||||||
if (_ptr_base <= ptr_loc && ptr_loc < _ptr_end) {
|
if (_ptr_base <= ptr_loc && ptr_loc < _ptr_end) {
|
||||||
address value = *ptr_loc;
|
address value = *ptr_loc;
|
||||||
|
// We don't want any pointer that points to very bottom of the archive, otherwise when
|
||||||
|
// MetaspaceShared::default_base_address()==0, we can't distinguish between a pointer
|
||||||
|
// to nothing (NULL) vs a pointer to an objects that happens to be at the very bottom
|
||||||
|
// of the archive.
|
||||||
|
assert(value != (address)_ptr_base, "don't point to the bottom of the archive");
|
||||||
|
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
assert(uintx(ptr_loc) % sizeof(intptr_t) == 0, "pointers must be stored in aligned addresses");
|
assert(uintx(ptr_loc) % sizeof(intptr_t) == 0, "pointers must be stored in aligned addresses");
|
||||||
size_t idx = ptr_loc - _ptr_base;
|
size_t idx = ptr_loc - _ptr_base;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -52,6 +52,7 @@ inline bool SharedDataRelocator<COMPACTING>::do_bit(size_t offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
address new_ptr = old_ptr + _delta;
|
address new_ptr = old_ptr + _delta;
|
||||||
|
assert(new_ptr != NULL, "don't point to the bottom of the archive"); // See ArchivePtrMarker::mark_pointer().
|
||||||
assert(_valid_new_base <= new_ptr && new_ptr < _valid_new_end, "must be");
|
assert(_valid_new_base <= new_ptr && new_ptr < _valid_new_end, "must be");
|
||||||
|
|
||||||
DEBUG_ONLY(log_trace(cds, reloc)("Patch2: @%8d [" PTR_FORMAT "] " PTR_FORMAT " -> " PTR_FORMAT,
|
DEBUG_ONLY(log_trace(cds, reloc)("Patch2: @%8d [" PTR_FORMAT "] " PTR_FORMAT " -> " PTR_FORMAT,
|
||||||
|
|
|
@ -966,13 +966,13 @@ void DynamicArchiveBuilder::relocate_buffer_to_target() {
|
||||||
if (addr_delta == 0) {
|
if (addr_delta == 0) {
|
||||||
ArchivePtrMarker::compact(relocatable_base, relocatable_end);
|
ArchivePtrMarker::compact(relocatable_base, relocatable_end);
|
||||||
} else {
|
} else {
|
||||||
// The base archive is NOT mapped at Arguments::default_SharedBaseAddress() (due to ASLR).
|
// The base archive is NOT mapped at MetaspaceShared::requested_base_address() (due to ASLR).
|
||||||
// This means that the current content of the dynamic archive is based on a random
|
// This means that the current content of the dynamic archive is based on a random
|
||||||
// address. Let's relocate all the pointers, so that it can be mapped to
|
// address. Let's relocate all the pointers, so that it can be mapped to
|
||||||
// Arguments::default_SharedBaseAddress() without runtime relocation.
|
// MetaspaceShared::requested_base_address() without runtime relocation.
|
||||||
//
|
//
|
||||||
// Note: both the base and dynamic archive are written with
|
// Note: both the base and dynamic archive are written with
|
||||||
// FileMapHeader::_shared_base_address == Arguments::default_SharedBaseAddress()
|
// FileMapHeader::_requested_base_address == MetaspaceShared::requested_base_address()
|
||||||
|
|
||||||
// Patch all pointers that are marked by ptrmap within this region,
|
// Patch all pointers that are marked by ptrmap within this region,
|
||||||
// where we have just dumped all the metaspace data.
|
// where we have just dumped all the metaspace data.
|
||||||
|
@ -992,7 +992,7 @@ void DynamicArchiveBuilder::relocate_buffer_to_target() {
|
||||||
|
|
||||||
// after patching, the pointers must point inside this range
|
// after patching, the pointers must point inside this range
|
||||||
// (the requested location of the archive, as mapped at runtime).
|
// (the requested location of the archive, as mapped at runtime).
|
||||||
address valid_new_base = (address)Arguments::default_SharedBaseAddress();
|
address valid_new_base = (address)MetaspaceShared::requested_base_address();
|
||||||
address valid_new_end = valid_new_base + base_plus_top_size;
|
address valid_new_end = valid_new_base + base_plus_top_size;
|
||||||
|
|
||||||
log_debug(cds)("Relocating archive from [" INTPTR_FORMAT " - " INTPTR_FORMAT "] to "
|
log_debug(cds)("Relocating archive from [" INTPTR_FORMAT " - " INTPTR_FORMAT "] to "
|
||||||
|
@ -1020,7 +1020,7 @@ void DynamicArchiveBuilder::write_archive(char* serialized_data) {
|
||||||
const char* archive_name = Arguments::GetSharedDynamicArchivePath();
|
const char* archive_name = Arguments::GetSharedDynamicArchivePath();
|
||||||
dynamic_info->open_for_write(archive_name);
|
dynamic_info->open_for_write(archive_name);
|
||||||
MetaspaceShared::write_core_archive_regions(dynamic_info, NULL, NULL);
|
MetaspaceShared::write_core_archive_regions(dynamic_info, NULL, NULL);
|
||||||
dynamic_info->set_final_requested_base((char*)Arguments::default_SharedBaseAddress());
|
dynamic_info->set_final_requested_base((char*)MetaspaceShared::requested_base_address());
|
||||||
dynamic_info->set_header_crc(dynamic_info->compute_header_crc());
|
dynamic_info->set_header_crc(dynamic_info->compute_header_crc());
|
||||||
dynamic_info->write_header();
|
dynamic_info->write_header();
|
||||||
dynamic_info->close();
|
dynamic_info->close();
|
||||||
|
|
|
@ -88,6 +88,7 @@ address MetaspaceShared::_i2i_entry_code_buffers = NULL;
|
||||||
size_t MetaspaceShared::_i2i_entry_code_buffers_size = 0;
|
size_t MetaspaceShared::_i2i_entry_code_buffers_size = 0;
|
||||||
void* MetaspaceShared::_shared_metaspace_static_top = NULL;
|
void* MetaspaceShared::_shared_metaspace_static_top = NULL;
|
||||||
intx MetaspaceShared::_relocation_delta;
|
intx MetaspaceShared::_relocation_delta;
|
||||||
|
char* MetaspaceShared::_requested_base_address;
|
||||||
|
|
||||||
// The CDS archive is divided into the following regions:
|
// The CDS archive is divided into the following regions:
|
||||||
// mc - misc code (the method entry trampolines, c++ vtables)
|
// mc - misc code (the method entry trampolines, c++ vtables)
|
||||||
|
@ -240,33 +241,53 @@ char* MetaspaceShared::read_only_space_alloc(size_t num_bytes) {
|
||||||
|
|
||||||
size_t MetaspaceShared::reserved_space_alignment() { return os::vm_allocation_granularity(); }
|
size_t MetaspaceShared::reserved_space_alignment() { return os::vm_allocation_granularity(); }
|
||||||
|
|
||||||
|
static bool shared_base_valid(char* shared_base) {
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
// Check SharedBaseAddress for validity. At this point, os::init() must
|
return CompressedKlassPointers::is_valid_base((address)shared_base);
|
||||||
// have been ran.
|
#else
|
||||||
static void check_SharedBaseAddress() {
|
return true;
|
||||||
SharedBaseAddress = align_up(SharedBaseAddress,
|
|
||||||
MetaspaceShared::reserved_space_alignment());
|
|
||||||
if (!CompressedKlassPointers::is_valid_base((address)SharedBaseAddress)) {
|
|
||||||
log_warning(cds)("SharedBaseAddress=" PTR_FORMAT " is invalid for this "
|
|
||||||
"platform, option will be ignored.",
|
|
||||||
p2i((address)SharedBaseAddress));
|
|
||||||
SharedBaseAddress = Arguments::default_SharedBaseAddress();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool shared_base_too_high(char* shared_base, size_t cds_total) {
|
||||||
|
if (SharedBaseAddress != 0 && shared_base < (char*)SharedBaseAddress) {
|
||||||
|
// SharedBaseAddress is very high (e.g., 0xffffffffffffff00) so
|
||||||
|
// align_up(SharedBaseAddress, MetaspaceShared::reserved_space_alignment()) has wrapped around.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (max_uintx - uintx(shared_base) < uintx(cds_total)) {
|
||||||
|
// The end of the archive will wrap around
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* compute_shared_base(size_t cds_total) {
|
||||||
|
char* shared_base = (char*)align_up((char*)SharedBaseAddress, MetaspaceShared::reserved_space_alignment());
|
||||||
|
const char* err = NULL;
|
||||||
|
if (shared_base_too_high(shared_base, cds_total)) {
|
||||||
|
err = "too high";
|
||||||
|
} else if (!shared_base_valid(shared_base)) {
|
||||||
|
err = "invalid for this platform";
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
|
log_warning(cds)("SharedBaseAddress (" INTPTR_FORMAT ") is %s. Reverted to " INTPTR_FORMAT,
|
||||||
|
p2i((void*)SharedBaseAddress), err,
|
||||||
|
p2i((void*)Arguments::default_SharedBaseAddress()));
|
||||||
|
SharedBaseAddress = Arguments::default_SharedBaseAddress();
|
||||||
|
shared_base = (char*)align_up((char*)SharedBaseAddress, MetaspaceShared::reserved_space_alignment());
|
||||||
|
}
|
||||||
|
assert(!shared_base_too_high(shared_base, cds_total) && shared_base_valid(shared_base), "Sanity");
|
||||||
|
return shared_base;
|
||||||
|
}
|
||||||
|
|
||||||
void MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() {
|
void MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() {
|
||||||
assert(DumpSharedSpaces, "should be called for dump time only");
|
assert(DumpSharedSpaces, "should be called for dump time only");
|
||||||
|
|
||||||
#ifdef _LP64
|
|
||||||
check_SharedBaseAddress();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const size_t reserve_alignment = MetaspaceShared::reserved_space_alignment();
|
const size_t reserve_alignment = MetaspaceShared::reserved_space_alignment();
|
||||||
char* shared_base = (char*)align_up((char*)SharedBaseAddress, reserve_alignment);
|
|
||||||
|
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
assert(CompressedKlassPointers::is_valid_base((address)shared_base), "Sanity");
|
|
||||||
// On 64-bit VM we reserve a 4G range and, if UseCompressedClassPointers=1,
|
// On 64-bit VM we reserve a 4G range and, if UseCompressedClassPointers=1,
|
||||||
// will use that to house both the archives and the ccs. See below for
|
// will use that to house both the archives and the ccs. See below for
|
||||||
// details.
|
// details.
|
||||||
|
@ -278,6 +299,9 @@ void MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() {
|
||||||
size_t cds_total = align_down(256*M, reserve_alignment);
|
size_t cds_total = align_down(256*M, reserve_alignment);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char* shared_base = compute_shared_base(cds_total);
|
||||||
|
_requested_base_address = shared_base;
|
||||||
|
|
||||||
// Whether to use SharedBaseAddress as attach address.
|
// Whether to use SharedBaseAddress as attach address.
|
||||||
bool use_requested_base = true;
|
bool use_requested_base = true;
|
||||||
|
|
||||||
|
@ -398,6 +422,10 @@ void MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() {
|
||||||
log_info(cds)("Allocated shared space: " SIZE_FORMAT " bytes at " PTR_FORMAT,
|
log_info(cds)("Allocated shared space: " SIZE_FORMAT " bytes at " PTR_FORMAT,
|
||||||
_shared_rs.size(), p2i(_shared_rs.base()));
|
_shared_rs.size(), p2i(_shared_rs.base()));
|
||||||
|
|
||||||
|
// We don't want any valid object to be at the very bottom of the archive.
|
||||||
|
// See ArchivePtrMarker::mark_pointer().
|
||||||
|
MetaspaceShared::misc_code_space_alloc(16);
|
||||||
|
|
||||||
size_t symbol_rs_size = LP64_ONLY(3 * G) NOT_LP64(128 * M);
|
size_t symbol_rs_size = LP64_ONLY(3 * G) NOT_LP64(128 * M);
|
||||||
_symbol_rs = ReservedSpace(symbol_rs_size);
|
_symbol_rs = ReservedSpace(symbol_rs_size);
|
||||||
if (!_symbol_rs.is_reserved()) {
|
if (!_symbol_rs.is_reserved()) {
|
||||||
|
@ -1200,7 +1228,7 @@ private:
|
||||||
void print_bitmap_region_stats(size_t size, size_t total_size);
|
void print_bitmap_region_stats(size_t size, size_t total_size);
|
||||||
void print_heap_region_stats(GrowableArray<MemRegion> *heap_mem,
|
void print_heap_region_stats(GrowableArray<MemRegion> *heap_mem,
|
||||||
const char *name, size_t total_size);
|
const char *name, size_t total_size);
|
||||||
void relocate_to_default_base_address(CHeapBitMap* ptrmap);
|
void relocate_to_requested_base_address(CHeapBitMap* ptrmap);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -1568,18 +1596,18 @@ void VM_PopulateDumpSharedSpace::print_class_stats() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM_PopulateDumpSharedSpace::relocate_to_default_base_address(CHeapBitMap* ptrmap) {
|
void VM_PopulateDumpSharedSpace::relocate_to_requested_base_address(CHeapBitMap* ptrmap) {
|
||||||
intx addr_delta = MetaspaceShared::final_delta();
|
intx addr_delta = MetaspaceShared::final_delta();
|
||||||
if (addr_delta == 0) {
|
if (addr_delta == 0) {
|
||||||
ArchivePtrMarker::compact((address)SharedBaseAddress, (address)_ro_region.top());
|
ArchivePtrMarker::compact((address)SharedBaseAddress, (address)_ro_region.top());
|
||||||
} else {
|
} else {
|
||||||
// We are not able to reserve space at Arguments::default_SharedBaseAddress() (due to ASLR).
|
// We are not able to reserve space at MetaspaceShared::requested_base_address() (due to ASLR).
|
||||||
// This means that the current content of the archive is based on a random
|
// This means that the current content of the archive is based on a random
|
||||||
// address. Let's relocate all the pointers, so that it can be mapped to
|
// address. Let's relocate all the pointers, so that it can be mapped to
|
||||||
// Arguments::default_SharedBaseAddress() without runtime relocation.
|
// MetaspaceShared::requested_base_address() without runtime relocation.
|
||||||
//
|
//
|
||||||
// Note: both the base and dynamic archive are written with
|
// Note: both the base and dynamic archive are written with
|
||||||
// FileMapHeader::_shared_base_address == Arguments::default_SharedBaseAddress()
|
// FileMapHeader::_requested_base_address == MetaspaceShared::requested_base_address()
|
||||||
|
|
||||||
// Patch all pointers that are marked by ptrmap within this region,
|
// Patch all pointers that are marked by ptrmap within this region,
|
||||||
// where we have just dumped all the metaspace data.
|
// where we have just dumped all the metaspace data.
|
||||||
|
@ -1594,7 +1622,7 @@ void VM_PopulateDumpSharedSpace::relocate_to_default_base_address(CHeapBitMap* p
|
||||||
|
|
||||||
// after patching, the pointers must point inside this range
|
// after patching, the pointers must point inside this range
|
||||||
// (the requested location of the archive, as mapped at runtime).
|
// (the requested location of the archive, as mapped at runtime).
|
||||||
address valid_new_base = (address)Arguments::default_SharedBaseAddress();
|
address valid_new_base = (address)MetaspaceShared::requested_base_address();
|
||||||
address valid_new_end = valid_new_base + size;
|
address valid_new_end = valid_new_base + size;
|
||||||
|
|
||||||
log_debug(cds)("Relocating archive from [" INTPTR_FORMAT " - " INTPTR_FORMAT " ] to "
|
log_debug(cds)("Relocating archive from [" INTPTR_FORMAT " - " INTPTR_FORMAT " ] to "
|
||||||
|
@ -1681,9 +1709,9 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||||
memset(MetaspaceShared::i2i_entry_code_buffers(), 0,
|
memset(MetaspaceShared::i2i_entry_code_buffers(), 0,
|
||||||
MetaspaceShared::i2i_entry_code_buffers_size());
|
MetaspaceShared::i2i_entry_code_buffers_size());
|
||||||
|
|
||||||
// relocate the data so that it can be mapped to Arguments::default_SharedBaseAddress()
|
// relocate the data so that it can be mapped to MetaspaceShared::requested_base_address()
|
||||||
// without runtime relocation.
|
// without runtime relocation.
|
||||||
relocate_to_default_base_address(&ptrmap);
|
relocate_to_requested_base_address(&ptrmap);
|
||||||
|
|
||||||
// Create and write the archive file that maps the shared spaces.
|
// Create and write the archive file that maps the shared spaces.
|
||||||
|
|
||||||
|
@ -1706,7 +1734,7 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||||
MetaspaceShared::first_open_archive_heap_region,
|
MetaspaceShared::first_open_archive_heap_region,
|
||||||
MetaspaceShared::max_open_archive_heap_region);
|
MetaspaceShared::max_open_archive_heap_region);
|
||||||
|
|
||||||
mapinfo->set_final_requested_base((char*)Arguments::default_SharedBaseAddress());
|
mapinfo->set_final_requested_base((char*)MetaspaceShared::requested_base_address());
|
||||||
mapinfo->set_header_crc(mapinfo->compute_header_crc());
|
mapinfo->set_header_crc(mapinfo->compute_header_crc());
|
||||||
mapinfo->write_header();
|
mapinfo->write_header();
|
||||||
print_region_stats(mapinfo);
|
print_region_stats(mapinfo);
|
||||||
|
@ -2162,6 +2190,7 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
|
||||||
} else {
|
} else {
|
||||||
FileMapInfo::set_shared_path_table(static_mapinfo);
|
FileMapInfo::set_shared_path_table(static_mapinfo);
|
||||||
}
|
}
|
||||||
|
_requested_base_address = static_mapinfo->requested_base_address();
|
||||||
} else {
|
} else {
|
||||||
set_shared_metaspace_range(NULL, NULL, NULL);
|
set_shared_metaspace_range(NULL, NULL, NULL);
|
||||||
UseSharedSpaces = false;
|
UseSharedSpaces = false;
|
||||||
|
@ -2209,6 +2238,11 @@ FileMapInfo* MetaspaceShared::open_dynamic_archive() {
|
||||||
// false = map at an alternative address picked by OS.
|
// false = map at an alternative address picked by OS.
|
||||||
MapArchiveResult MetaspaceShared::map_archives(FileMapInfo* static_mapinfo, FileMapInfo* dynamic_mapinfo,
|
MapArchiveResult MetaspaceShared::map_archives(FileMapInfo* static_mapinfo, FileMapInfo* dynamic_mapinfo,
|
||||||
bool use_requested_addr) {
|
bool use_requested_addr) {
|
||||||
|
if (use_requested_addr && static_mapinfo->requested_base_address() == NULL) {
|
||||||
|
log_info(cds)("Archive(s) were created with -XX:SharedBaseAddress=0. Always map at os-selected address.");
|
||||||
|
return MAP_ARCHIVE_MMAP_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
PRODUCT_ONLY(if (ArchiveRelocationMode == 1 && use_requested_addr) {
|
PRODUCT_ONLY(if (ArchiveRelocationMode == 1 && use_requested_addr) {
|
||||||
// For product build only -- this is for benchmarking the cost of doing relocation.
|
// For product build only -- this is for benchmarking the cost of doing relocation.
|
||||||
// For debug builds, the check is done below, after reserving the space, for better test coverage
|
// For debug builds, the check is done below, after reserving the space, for better test coverage
|
||||||
|
@ -2660,11 +2694,11 @@ void MetaspaceShared::report_out_of_space(const char* name, size_t needed_bytes)
|
||||||
"Please reduce the number of shared classes.");
|
"Please reduce the number of shared classes.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is used to relocate the pointers so that the archive can be mapped at
|
// This is used to relocate the pointers so that the base archive can be mapped at
|
||||||
// Arguments::default_SharedBaseAddress() without runtime relocation.
|
// MetaspaceShared::requested_base_address() without runtime relocation.
|
||||||
intx MetaspaceShared::final_delta() {
|
intx MetaspaceShared::final_delta() {
|
||||||
return intx(Arguments::default_SharedBaseAddress()) // We want the archive to be mapped to here at runtime
|
return intx(MetaspaceShared::requested_base_address()) // We want the base archive to be mapped to here at runtime
|
||||||
- intx(SharedBaseAddress); // .. but the archive is mapped at here at dump time
|
- intx(SharedBaseAddress); // .. but the base archive is mapped at here at dump time
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaspaceShared::print_on(outputStream* st) {
|
void MetaspaceShared::print_on(outputStream* st) {
|
||||||
|
|
|
@ -183,6 +183,7 @@ class MetaspaceShared : AllStatic {
|
||||||
static size_t _core_spaces_size;
|
static size_t _core_spaces_size;
|
||||||
static void* _shared_metaspace_static_top;
|
static void* _shared_metaspace_static_top;
|
||||||
static intx _relocation_delta;
|
static intx _relocation_delta;
|
||||||
|
static char* _requested_base_address;
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
// core archive spaces
|
// core archive spaces
|
||||||
|
@ -353,6 +354,12 @@ class MetaspaceShared : AllStatic {
|
||||||
static intptr_t* fix_cpp_vtable_for_dynamic_archive(MetaspaceObj::Type msotype, address obj);
|
static intptr_t* fix_cpp_vtable_for_dynamic_archive(MetaspaceObj::Type msotype, address obj);
|
||||||
static void initialize_ptr_marker(CHeapBitMap* ptrmap);
|
static void initialize_ptr_marker(CHeapBitMap* ptrmap);
|
||||||
|
|
||||||
|
// This is the base address as specified by -XX:SharedBaseAddress during -Xshare:dump.
|
||||||
|
// Both the base/top archives are written using this as their base address.
|
||||||
|
static char* requested_base_address() {
|
||||||
|
return _requested_base_address;
|
||||||
|
}
|
||||||
|
|
||||||
// Non-zero if the archive(s) need to be mapped a non-default location due to ASLR.
|
// Non-zero if the archive(s) need to be mapped a non-default location due to ASLR.
|
||||||
static intx relocation_delta() { return _relocation_delta; }
|
static intx relocation_delta() { return _relocation_delta; }
|
||||||
static intx final_delta();
|
static intx final_delta();
|
||||||
|
|
|
@ -85,7 +85,7 @@ bool Arguments::_BackgroundCompilation = BackgroundCompilation;
|
||||||
bool Arguments::_ClipInlining = ClipInlining;
|
bool Arguments::_ClipInlining = ClipInlining;
|
||||||
intx Arguments::_Tier3InvokeNotifyFreqLog = Tier3InvokeNotifyFreqLog;
|
intx Arguments::_Tier3InvokeNotifyFreqLog = Tier3InvokeNotifyFreqLog;
|
||||||
intx Arguments::_Tier4InvocationThreshold = Tier4InvocationThreshold;
|
intx Arguments::_Tier4InvocationThreshold = Tier4InvocationThreshold;
|
||||||
size_t Arguments::_SharedBaseAddress = SharedBaseAddress;
|
size_t Arguments::_default_SharedBaseAddress = SharedBaseAddress;
|
||||||
|
|
||||||
bool Arguments::_enable_preview = false;
|
bool Arguments::_enable_preview = false;
|
||||||
|
|
||||||
|
@ -2281,8 +2281,8 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs *vm_options_args,
|
||||||
Arguments::_Tier4InvocationThreshold = Tier4InvocationThreshold;
|
Arguments::_Tier4InvocationThreshold = Tier4InvocationThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CDS dumping always write the archive to the default value of SharedBaseAddress.
|
// Remember the default value of SharedBaseAddress.
|
||||||
Arguments::_SharedBaseAddress = SharedBaseAddress;
|
Arguments::_default_SharedBaseAddress = SharedBaseAddress;
|
||||||
|
|
||||||
// Setup flags for mixed which is the default
|
// Setup flags for mixed which is the default
|
||||||
set_mode_flags(_mixed);
|
set_mode_flags(_mixed);
|
||||||
|
|
|
@ -489,7 +489,7 @@ class Arguments : AllStatic {
|
||||||
|
|
||||||
static char* SharedArchivePath;
|
static char* SharedArchivePath;
|
||||||
static char* SharedDynamicArchivePath;
|
static char* SharedDynamicArchivePath;
|
||||||
static size_t _SharedBaseAddress; // The default value specified in globals.hpp
|
static size_t _default_SharedBaseAddress; // The default value specified in globals.hpp
|
||||||
static int num_archives(const char* archive_path) NOT_CDS_RETURN_(0);
|
static int num_archives(const char* archive_path) NOT_CDS_RETURN_(0);
|
||||||
static void extract_shared_archive_paths(const char* archive_path,
|
static void extract_shared_archive_paths(const char* archive_path,
|
||||||
char** base_archive_path,
|
char** base_archive_path,
|
||||||
|
@ -572,7 +572,7 @@ class Arguments : AllStatic {
|
||||||
|
|
||||||
static const char* GetSharedArchivePath() { return SharedArchivePath; }
|
static const char* GetSharedArchivePath() { return SharedArchivePath; }
|
||||||
static const char* GetSharedDynamicArchivePath() { return SharedDynamicArchivePath; }
|
static const char* GetSharedDynamicArchivePath() { return SharedDynamicArchivePath; }
|
||||||
static size_t default_SharedBaseAddress() { return _SharedBaseAddress; }
|
static size_t default_SharedBaseAddress() { return _default_SharedBaseAddress; }
|
||||||
// Java launcher properties
|
// Java launcher properties
|
||||||
static void process_sun_java_launcher_properties(JavaVMInitArgs* args);
|
static void process_sun_java_launcher_properties(JavaVMInitArgs* args);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -40,7 +40,13 @@ public class SharedBaseAddress {
|
||||||
private static final String[] testTable = {
|
private static final String[] testTable = {
|
||||||
"1g", "8g", "64g","512g", "4t",
|
"1g", "8g", "64g","512g", "4t",
|
||||||
"32t", "128t", "0",
|
"32t", "128t", "0",
|
||||||
"1", "64k", "64M"
|
"1", "64k", "64M",
|
||||||
|
"0xfffffffffff00000", // archive top wraps around 64-bit address space
|
||||||
|
"0xfff80000", // archive top wraps around 32-bit address space
|
||||||
|
"0xffffffffffffffff", // archive bottom wraps around 64-bit address space -- due to align_up()
|
||||||
|
"0xffffffff", // archive bottom wraps around 32-bit address space -- due to align_up()
|
||||||
|
"0x00007ffffff00000", // end of archive will go past the end of user space on linux/x64
|
||||||
|
"0", // always let OS pick the base address at runtime (ASLR for CDS archive)
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -50,10 +56,16 @@ public class SharedBaseAddress {
|
||||||
System.out.println("sharedBaseAddress = " + testEntry);
|
System.out.println("sharedBaseAddress = " + testEntry);
|
||||||
CDSOptions opts = (new CDSOptions())
|
CDSOptions opts = (new CDSOptions())
|
||||||
.setArchiveName(filename)
|
.setArchiveName(filename)
|
||||||
.addPrefix("-XX:SharedBaseAddress=" + testEntry);
|
.addPrefix("-XX:SharedBaseAddress=" + testEntry)
|
||||||
|
.addPrefix("-Xlog:cds=debug")
|
||||||
|
.addPrefix("-Xlog:cds+reloc=debug");
|
||||||
|
|
||||||
CDSTestUtils.createArchiveAndCheck(opts);
|
CDSTestUtils.createArchiveAndCheck(opts);
|
||||||
CDSTestUtils.runWithArchiveAndCheck(opts);
|
OutputAnalyzer out = CDSTestUtils.runWithArchiveAndCheck(opts);
|
||||||
|
if (testEntry.equals("0")) {
|
||||||
|
out.shouldContain("Archive(s) were created with -XX:SharedBaseAddress=0. Always map at os-selected address.")
|
||||||
|
.shouldContain("Try to map archive(s) at an alternative address");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary Test how the dynamic archive handles -XX:SharedBaseAddress
|
||||||
|
* @requires vm.cds
|
||||||
|
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes
|
||||||
|
* @build Hello
|
||||||
|
* @build sun.hotspot.WhiteBox
|
||||||
|
* @run driver ClassFileInstaller -jar hello.jar Hello
|
||||||
|
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. SharedBaseAddressOption
|
||||||
|
*/
|
||||||
|
|
||||||
|
import jdk.test.lib.Platform;
|
||||||
|
|
||||||
|
public class SharedBaseAddressOption extends DynamicArchiveTestBase {
|
||||||
|
static String appJar = ClassFileInstaller.getJarPath("hello.jar");
|
||||||
|
static String mainClass = "Hello";
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
runTest(SharedBaseAddressOption::testCustomBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void testCustomBase() throws Exception {
|
||||||
|
|
||||||
|
// (1) -XX:SharedBaseAddress=0 -- the archives will always be relocated at runtime
|
||||||
|
doTest("0");
|
||||||
|
|
||||||
|
// (2) -XX:SharedBaseAddress=0x810000000
|
||||||
|
if (Platform.is64bit()) {
|
||||||
|
doTest("0x810000000");
|
||||||
|
}
|
||||||
|
|
||||||
|
// (3) -XX:SharedBaseAddress that's so high that the archive may wrap around 64-bit
|
||||||
|
if (Platform.is64bit()) {
|
||||||
|
doTest("0xfffffffffff00000");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void doTest(String sharedBase) throws Exception {
|
||||||
|
String baseArchiveName = getNewArchiveName("base");
|
||||||
|
String topArchiveName = getNewArchiveName("top");
|
||||||
|
|
||||||
|
TestCommon.dumpBaseArchive(baseArchiveName, "-XX:SharedBaseAddress=" + sharedBase,
|
||||||
|
"-Xlog:cds=debug",
|
||||||
|
"-Xlog:cds+reloc=debug",
|
||||||
|
"-Xlog:cds+dynamic=debug");
|
||||||
|
|
||||||
|
dump2(baseArchiveName, topArchiveName,
|
||||||
|
"-Xlog:cds=debug",
|
||||||
|
"-Xlog:cds+reloc=debug",
|
||||||
|
"-Xlog:cds+dynamic=debug",
|
||||||
|
"-cp", appJar, mainClass)
|
||||||
|
.assertNormalExit();
|
||||||
|
|
||||||
|
// a top archive specified in the base archive position
|
||||||
|
run2(baseArchiveName, topArchiveName,
|
||||||
|
"-Xlog:cds=debug",
|
||||||
|
"-Xlog:cds+reloc=debug",
|
||||||
|
"-Xlog:cds+dynamic=debug",
|
||||||
|
"-cp", appJar, mainClass)
|
||||||
|
.assertNormalExit();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue