8208658: Make CDS archived heap regions usable even if compressed oop encoding has changed
Relocate and patch archive regions if necessary Reviewed-by: jiangli, tschatzl
This commit is contained in:
parent
aafb128d89
commit
5b2c081460
@ -27,6 +27,7 @@
|
||||
#include "classfile/compactHashtable.inline.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "logging/logMessage.hpp"
|
||||
#include "memory/heapShared.inline.hpp"
|
||||
#include "memory/metadataFactory.hpp"
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
#include "oops/compressedOops.inline.hpp"
|
||||
@ -280,8 +281,9 @@ class CompactHashtable_OopIterator {
|
||||
public:
|
||||
CompactHashtable_OopIterator(OopClosure *cl) : _closure(cl) {}
|
||||
inline void do_value(address base_address, u4 offset) const {
|
||||
narrowOop o = (narrowOop)offset;
|
||||
_closure->do_oop(&o);
|
||||
narrowOop v = (narrowOop)offset;
|
||||
oop obj = HeapShared::decode_with_archived_oop_encoding_mode(v);
|
||||
_closure->do_oop(&obj);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -28,7 +28,8 @@
|
||||
#include "classfile/compactHashtable.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "oops/compressedOops.inline.hpp"
|
||||
#include "memory/filemap.hpp"
|
||||
#include "memory/heapShared.inline.hpp"
|
||||
#include "oops/oop.hpp"
|
||||
|
||||
template <class T, class N>
|
||||
@ -46,8 +47,8 @@ inline Symbol* CompactHashtable<T, N>::decode_entry(CompactHashtable<Symbol*, ch
|
||||
template <class T, class N>
|
||||
inline oop CompactHashtable<T, N>::decode_entry(CompactHashtable<oop, char>* const t,
|
||||
u4 offset, const char* name, int len) {
|
||||
narrowOop obj = (narrowOop)offset;
|
||||
oop string = CompressedOops::decode(obj);
|
||||
narrowOop v = (narrowOop)offset;
|
||||
oop string = HeapShared::decode_with_archived_oop_encoding_mode(v);
|
||||
if (java_lang_String::equals(string, (jchar*)name, len)) {
|
||||
return string;
|
||||
}
|
||||
|
@ -1213,7 +1213,7 @@ oop java_lang_Class::process_archived_mirror(Klass* k, oop mirror,
|
||||
bool java_lang_Class::restore_archived_mirror(Klass *k,
|
||||
Handle class_loader, Handle module,
|
||||
Handle protection_domain, TRAPS) {
|
||||
oop m = MetaspaceShared::materialize_archived_object(k->archived_java_mirror_raw());
|
||||
oop m = MetaspaceShared::materialize_archived_object(k->archived_java_mirror_raw_narrow());
|
||||
|
||||
if (m == NULL) {
|
||||
return false;
|
||||
|
@ -59,8 +59,8 @@ class StringDedupSharedClosure: public OopClosure {
|
||||
public:
|
||||
StringDedupSharedClosure(StringDedupStat* stat) : _stat(stat) {}
|
||||
|
||||
virtual void do_oop(oop* p) { ShouldNotReachHere(); }
|
||||
virtual void do_oop(narrowOop* p) {
|
||||
virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
|
||||
virtual void do_oop(oop* p) {
|
||||
oop java_string = RawAccess<>::oop_load(p);
|
||||
StringDedupTable::deduplicate(java_string, _stat);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
#define NUM_CDS_REGIONS 9
|
||||
#define CDS_ARCHIVE_MAGIC 0xf00baba2
|
||||
#define CURRENT_CDS_ARCHIVE_VERSION 4
|
||||
#define CURRENT_CDS_ARCHIVE_VERSION 5
|
||||
#define INVALID_CDS_ARCHIVE_VERSION -1
|
||||
|
||||
struct CDSFileMapRegion {
|
||||
@ -49,6 +49,8 @@ struct CDSFileMapRegion {
|
||||
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;
|
||||
};
|
||||
|
||||
struct CDSFileMapHeaderBase {
|
||||
|
@ -35,12 +35,15 @@
|
||||
#include "logging/logStream.hpp"
|
||||
#include "logging/logMessage.hpp"
|
||||
#include "memory/filemap.hpp"
|
||||
#include "memory/heapShared.inline.hpp"
|
||||
#include "memory/iterator.inline.hpp"
|
||||
#include "memory/metadataFactory.hpp"
|
||||
#include "memory/metaspaceClosure.hpp"
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
#include "memory/oopFactory.hpp"
|
||||
#include "oops/compressedOops.inline.hpp"
|
||||
#include "oops/objArrayOop.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
@ -51,6 +54,7 @@
|
||||
#include "utilities/defaultStream.hpp"
|
||||
#if INCLUDE_G1GC
|
||||
#include "gc/g1/g1CollectedHeap.hpp"
|
||||
#include "gc/g1/heapRegion.hpp"
|
||||
#endif
|
||||
|
||||
# include <sys/stat.h>
|
||||
@ -188,6 +192,9 @@ void FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
|
||||
_shared_path_table_size = mapinfo->_shared_path_table_size;
|
||||
_shared_path_table = mapinfo->_shared_path_table;
|
||||
_shared_path_entry_size = mapinfo->_shared_path_entry_size;
|
||||
if (MetaspaceShared::is_heap_object_archiving_allowed()) {
|
||||
_heap_reserved = Universe::heap()->reserved_region();
|
||||
}
|
||||
|
||||
// The following fields are for sanity checks for whether this archive
|
||||
// will function correctly with this JVM and the bootclasspath it's
|
||||
@ -653,13 +660,14 @@ void FileMapInfo::write_region(int region, char* base, size_t size,
|
||||
// "_" represented unused spaced in the heap region.
|
||||
//
|
||||
//
|
||||
// |ah0 | ah1 | ah2| ...... | ahn |
|
||||
// |ah0 | ah1 | ah2| ...... | ahn|
|
||||
// |XXXXXX|__ |XXXXX|XXXX|XXXXXXXX|XXXX|
|
||||
// |<-r0->| |<- r1 ----------------->|
|
||||
// ^^^
|
||||
// |
|
||||
// +-- gap
|
||||
size_t FileMapInfo::write_archive_heap_regions(GrowableArray<MemRegion> *heap_mem,
|
||||
GrowableArray<ArchiveHeapOopmapInfo> *oopmaps,
|
||||
int first_region_id, int max_num_regions) {
|
||||
assert(max_num_regions <= 2, "Only support maximum 2 memory regions");
|
||||
|
||||
@ -684,6 +692,10 @@ size_t FileMapInfo::write_archive_heap_regions(GrowableArray<MemRegion> *heap_me
|
||||
log_info(cds)("Archive heap region %d " INTPTR_FORMAT " - " INTPTR_FORMAT " = " SIZE_FORMAT_W(8) " bytes",
|
||||
i, p2i(start), p2i(start + size), size);
|
||||
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;
|
||||
}
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
@ -762,7 +774,7 @@ bool FileMapInfo::remap_shared_readonly_as_readwrite() {
|
||||
if (!open_for_read()) {
|
||||
return false;
|
||||
}
|
||||
char *addr = _header->region_addr(idx);
|
||||
char *addr = region_addr(idx);
|
||||
char *base = os::remap_memory(_fd, _full_path, si->_file_offset,
|
||||
addr, size, false /* !read_only */,
|
||||
si->_allow_exec);
|
||||
@ -781,7 +793,7 @@ bool FileMapInfo::remap_shared_readonly_as_readwrite() {
|
||||
|
||||
// Map the whole region at once, assumed to be allocated contiguously.
|
||||
ReservedSpace FileMapInfo::reserve_shared_memory() {
|
||||
char* requested_addr = _header->region_addr(0);
|
||||
char* requested_addr = region_addr(0);
|
||||
size_t size = FileMapInfo::core_spaces_size();
|
||||
|
||||
// Reserve the space first, then map otherwise map will go right over some
|
||||
@ -808,7 +820,7 @@ char* FileMapInfo::map_region(int i, char** top_ret) {
|
||||
size_t used = si->_used;
|
||||
size_t alignment = os::vm_allocation_granularity();
|
||||
size_t size = align_up(used, alignment);
|
||||
char *requested_addr = _header->region_addr(i);
|
||||
char *requested_addr = region_addr(i);
|
||||
|
||||
// If a tool agent is in use (debugging enabled), we must map the address space RW
|
||||
if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space()) {
|
||||
@ -838,19 +850,57 @@ char* FileMapInfo::map_region(int i, char** top_ret) {
|
||||
return base;
|
||||
}
|
||||
|
||||
address FileMapInfo::decode_start_address(CDSFileMapRegion* spc, bool with_current_oop_encoding_mode) {
|
||||
if (with_current_oop_encoding_mode) {
|
||||
return (address)CompressedOops::decode_not_null(offset_of_space(spc));
|
||||
} else {
|
||||
return (address)HeapShared::decode_with_archived_oop_encoding_mode(offset_of_space(spc));
|
||||
}
|
||||
}
|
||||
|
||||
static MemRegion *string_ranges = NULL;
|
||||
static MemRegion *open_archive_heap_ranges = NULL;
|
||||
static int num_string_ranges = 0;
|
||||
static int num_open_archive_heap_ranges = 0;
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
bool FileMapInfo::has_heap_regions() {
|
||||
return (_header->_space[MetaspaceShared::first_string]._used > 0);
|
||||
}
|
||||
|
||||
// Returns the address range of the archived heap regions computed using the
|
||||
// current oop encoding mode. This range may be different than the one seen at
|
||||
// dump time due to encoding mode differences. The result is used in determining
|
||||
// if/how these regions should be relocated at run time.
|
||||
MemRegion FileMapInfo::get_heap_regions_range_with_current_oop_encoding_mode() {
|
||||
address start = (address) max_uintx;
|
||||
address end = NULL;
|
||||
|
||||
for (int i = MetaspaceShared::first_string; i <= MetaspaceShared::last_valid_region; i++) {
|
||||
CDSFileMapRegion* si = space_at(i);
|
||||
size_t size = si->_used;
|
||||
if (size > 0) {
|
||||
address s = start_address_with_current_oop_encoding_mode(si);
|
||||
address e = s + size;
|
||||
if (start > s) {
|
||||
start = s;
|
||||
}
|
||||
if (end < e) {
|
||||
end = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(end != NULL, "must have at least one used heap region");
|
||||
return MemRegion((HeapWord*)start, (HeapWord*)end);
|
||||
}
|
||||
|
||||
//
|
||||
// Map the shared string objects and open archive heap objects to the runtime
|
||||
// java heap.
|
||||
//
|
||||
// The shared strings are mapped near the runtime java heap top. The
|
||||
// mapped strings contain no out-going references to any other java heap
|
||||
// regions. GC does not write into the mapped shared strings.
|
||||
// The shared strings are mapped close to the end of the java heap top in
|
||||
// closed archive regions. The mapped strings contain no out-going references
|
||||
// to any other java heap regions. GC does not write into the mapped shared strings.
|
||||
//
|
||||
// The open archive heap objects are mapped below the shared strings in
|
||||
// the runtime java heap. The mapped open archive heap data only contain
|
||||
@ -858,56 +908,110 @@ static int num_open_archive_heap_ranges = 0;
|
||||
// During runtime execution, out-going references to any other java heap
|
||||
// regions may be added. GC may mark and update references in the mapped
|
||||
// open archive objects.
|
||||
void FileMapInfo::map_heap_regions() {
|
||||
if (MetaspaceShared::is_heap_object_archiving_allowed()) {
|
||||
log_info(cds)("Archived narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
|
||||
narrow_oop_mode(), p2i(narrow_oop_base()), narrow_oop_shift());
|
||||
log_info(cds)("Archived narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
|
||||
p2i(narrow_klass_base()), narrow_klass_shift());
|
||||
void FileMapInfo::map_heap_regions_impl() {
|
||||
if (!MetaspaceShared::is_heap_object_archiving_allowed()) {
|
||||
log_info(cds)("CDS heap data is being ignored. UseG1GC, "
|
||||
"UseCompressedOops and UseCompressedClassPointers are required.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that all the narrow oop and klass encodings match the archive
|
||||
if (narrow_oop_mode() != Universe::narrow_oop_mode() ||
|
||||
narrow_oop_base() != Universe::narrow_oop_base() ||
|
||||
narrow_oop_shift() != Universe::narrow_oop_shift() ||
|
||||
narrow_klass_base() != Universe::narrow_klass_base() ||
|
||||
narrow_klass_shift() != Universe::narrow_klass_shift()) {
|
||||
if (log_is_enabled(Info, cds) && space_at(MetaspaceShared::first_string)->_used > 0) {
|
||||
log_info(cds)("Cached heap data from the CDS archive is being ignored. "
|
||||
"The current CompressedOops/CompressedClassPointers encoding differs from "
|
||||
"that archived due to heap size change. The archive was dumped using max heap "
|
||||
"size " UINTX_FORMAT "M.", max_heap_size()/M);
|
||||
log_info(cds)("Current narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
|
||||
Universe::narrow_oop_mode(), p2i(Universe::narrow_oop_base()),
|
||||
Universe::narrow_oop_shift());
|
||||
log_info(cds)("Current narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
|
||||
p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift());
|
||||
}
|
||||
} else {
|
||||
// First, map string regions as closed archive heap regions.
|
||||
// GC does not write into the regions.
|
||||
if (map_heap_data(&string_ranges,
|
||||
MetaspaceShared::first_string,
|
||||
MetaspaceShared::max_strings,
|
||||
&num_string_ranges)) {
|
||||
StringTable::set_shared_string_mapped();
|
||||
MemRegion heap_reserved = Universe::heap()->reserved_region();
|
||||
|
||||
// Now, map open_archive heap regions, GC can write into the regions.
|
||||
if (map_heap_data(&open_archive_heap_ranges,
|
||||
MetaspaceShared::first_open_archive_heap_region,
|
||||
MetaspaceShared::max_open_archive_heap_region,
|
||||
&num_open_archive_heap_ranges,
|
||||
true /* open */)) {
|
||||
MetaspaceShared::set_open_archive_heap_region_mapped();
|
||||
}
|
||||
}
|
||||
}
|
||||
log_info(cds)("CDS archive was created with max heap size = " SIZE_FORMAT "M, and the following configuration:",
|
||||
max_heap_size()/M);
|
||||
log_info(cds)(" narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
|
||||
p2i(narrow_klass_base()), narrow_klass_shift());
|
||||
log_info(cds)(" narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
|
||||
narrow_oop_mode(), p2i(narrow_oop_base()), narrow_oop_shift());
|
||||
|
||||
log_info(cds)("The current max heap size = " SIZE_FORMAT "M, HeapRegion::GrainBytes = " SIZE_FORMAT,
|
||||
heap_reserved.byte_size()/M, HeapRegion::GrainBytes);
|
||||
log_info(cds)(" narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
|
||||
p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift());
|
||||
log_info(cds)(" narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
|
||||
Universe::narrow_oop_mode(), p2i(Universe::narrow_oop_base()), Universe::narrow_oop_shift());
|
||||
|
||||
if (narrow_klass_base() != Universe::narrow_klass_base() ||
|
||||
narrow_klass_shift() != Universe::narrow_klass_shift()) {
|
||||
log_info(cds)("CDS heap data cannot be used because the archive was created with an incompatible narrow klass encoding mode.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (narrow_oop_mode() != Universe::narrow_oop_mode() ||
|
||||
narrow_oop_base() != Universe::narrow_oop_base() ||
|
||||
narrow_oop_shift() != Universe::narrow_oop_shift()) {
|
||||
log_info(cds)("CDS heap data need to be relocated because the archive was created with an incompatible oop encoding mode.");
|
||||
_heap_pointers_need_patching = true;
|
||||
} else {
|
||||
if (log_is_enabled(Info, cds) && space_at(MetaspaceShared::first_string)->_used > 0) {
|
||||
log_info(cds)("Cached heap data from the CDS archive is being ignored. UseG1GC, "
|
||||
"UseCompressedOops and UseCompressedClassPointers are required.");
|
||||
MemRegion range = get_heap_regions_range_with_current_oop_encoding_mode();
|
||||
if (!heap_reserved.contains(range)) {
|
||||
log_info(cds)("CDS heap data need to be relocated because");
|
||||
log_info(cds)("the desired range " PTR_FORMAT " - " PTR_FORMAT, p2i(range.start()), p2i(range.end()));
|
||||
log_info(cds)("is outside of the heap " PTR_FORMAT " - " PTR_FORMAT, p2i(heap_reserved.start()), p2i(heap_reserved.end()));
|
||||
_heap_pointers_need_patching = true;
|
||||
}
|
||||
}
|
||||
|
||||
ptrdiff_t delta = 0;
|
||||
if (_heap_pointers_need_patching) {
|
||||
// dumptime heap end ------------v
|
||||
// [ |archived heap regions| ] runtime heap end ------v
|
||||
// [ |archived heap regions| ]
|
||||
// |<-----delta-------------------->|
|
||||
//
|
||||
// At dump time, the archived heap regions were near the top of the heap.
|
||||
// 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_reserved.end();
|
||||
address runtime_heap_end = (address)heap_reserved.end();
|
||||
delta = runtime_heap_end - dumptime_heap_end;
|
||||
}
|
||||
|
||||
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_string);
|
||||
address relocated_strings_bottom = start_address_with_archived_oop_encoding_mode(si);
|
||||
if (!is_aligned(relocated_strings_bottom + delta, HeapRegion::GrainBytes)) {
|
||||
// Align the bottom of the string regions at G1 region boundary. This will avoid
|
||||
// the situation where the highest open region and the lowest string region sharing
|
||||
// the same G1 region. Otherwise we will fail to map the open regions.
|
||||
size_t align = size_t(relocated_strings_bottom) % HeapRegion::GrainBytes;
|
||||
delta -= align;
|
||||
assert(is_aligned(relocated_strings_bottom + delta, HeapRegion::GrainBytes), "must be");
|
||||
|
||||
log_info(cds)("CDS heap data need to be relocated lower by a further " SIZE_FORMAT
|
||||
" bytes to be aligned with HeapRegion::GrainBytes", align);
|
||||
|
||||
HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift());
|
||||
_heap_pointers_need_patching = true;
|
||||
}
|
||||
|
||||
// First, map string regions as closed archive heap regions.
|
||||
// GC does not write into the regions.
|
||||
if (map_heap_data(&string_ranges,
|
||||
MetaspaceShared::first_string,
|
||||
MetaspaceShared::max_strings,
|
||||
&num_string_ranges)) {
|
||||
StringTable::set_shared_string_mapped();
|
||||
|
||||
// Now, map open_archive heap regions, GC can write into the regions.
|
||||
if (map_heap_data(&open_archive_heap_ranges,
|
||||
MetaspaceShared::first_open_archive_heap_region,
|
||||
MetaspaceShared::max_open_archive_heap_region,
|
||||
&num_open_archive_heap_ranges,
|
||||
true /* open */)) {
|
||||
MetaspaceShared::set_open_archive_heap_region_mapped();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileMapInfo::map_heap_regions() {
|
||||
if (has_heap_regions()) {
|
||||
map_heap_regions_impl();
|
||||
}
|
||||
|
||||
if (!StringTable::shared_string_mapped()) {
|
||||
assert(string_ranges == NULL && num_string_ranges == 0, "sanity");
|
||||
}
|
||||
@ -926,13 +1030,13 @@ bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first,
|
||||
for (int i = first;
|
||||
i < first + max; i++) {
|
||||
si = space_at(i);
|
||||
size_t used = si->_used;
|
||||
if (used > 0) {
|
||||
size_t size = used;
|
||||
char* requested_addr = (char*)((void*)CompressedOops::decode_not_null(
|
||||
(narrowOop)si->_addr._offset));
|
||||
regions[region_num] = MemRegion((HeapWord*)requested_addr, size / HeapWordSize);
|
||||
size_t size = si->_used;
|
||||
if (size > 0) {
|
||||
HeapWord* start = (HeapWord*)start_address_with_archived_oop_encoding_mode(si);
|
||||
regions[region_num] = MemRegion(start, size / HeapWordSize);
|
||||
region_num ++;
|
||||
log_info(cds)("Trying to map heap data: region[%d] at " INTPTR_FORMAT ", size = " SIZE_FORMAT_W(8) " bytes",
|
||||
i, p2i(start), size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -942,16 +1046,14 @@ bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first,
|
||||
|
||||
// Check that ranges are within the java heap
|
||||
if (!G1CollectedHeap::heap()->check_archive_addresses(regions, region_num)) {
|
||||
log_info(cds)("UseSharedSpaces: Unable to allocate region, "
|
||||
"range is not within java heap.");
|
||||
log_info(cds)("UseSharedSpaces: Unable to allocate region, range is not within java heap.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// allocate from java heap
|
||||
if (!G1CollectedHeap::heap()->alloc_archive_regions(
|
||||
regions, region_num, is_open_archive)) {
|
||||
log_info(cds)("UseSharedSpaces: Unable to allocate region, "
|
||||
"java heap range is already in use.");
|
||||
log_info(cds)("UseSharedSpaces: Unable to allocate region, java heap range is already in use.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -967,7 +1069,9 @@ bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first,
|
||||
if (base == NULL || base != addr) {
|
||||
// dealloc the regions from java heap
|
||||
dealloc_archive_heap_regions(regions, region_num);
|
||||
log_info(cds)("UseSharedSpaces: Unable to map at required address in java heap.");
|
||||
log_info(cds)("UseSharedSpaces: Unable to map at required address in java heap. "
|
||||
INTPTR_FORMAT ", size = " SIZE_FORMAT " bytes",
|
||||
p2i(addr), regions[i].byte_size());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -995,6 +1099,31 @@ bool FileMapInfo::verify_mapped_heap_regions(int first, int num) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileMapInfo::patch_archived_heap_embedded_pointers() {
|
||||
if (!_heap_pointers_need_patching) {
|
||||
return;
|
||||
}
|
||||
|
||||
patch_archived_heap_embedded_pointers(string_ranges,
|
||||
num_string_ranges,
|
||||
MetaspaceShared::first_string);
|
||||
|
||||
patch_archived_heap_embedded_pointers(open_archive_heap_ranges,
|
||||
num_open_archive_heap_ranges,
|
||||
MetaspaceShared::first_open_archive_heap_region);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// This internally allocates objects using SystemDictionary::Object_klass(), so it
|
||||
// must be called after the well-known classes are resolved.
|
||||
void FileMapInfo::fixup_mapped_heap_regions() {
|
||||
// If any string regions were found, call the fill routine to make them parseable.
|
||||
// Note that string_ranges may be non-NULL even if no ranges were found.
|
||||
@ -1036,7 +1165,7 @@ bool FileMapInfo::verify_region_checksum(int i) {
|
||||
!MetaspaceShared::open_archive_heap_region_mapped())) {
|
||||
return true; // archived heap data is not mapped
|
||||
}
|
||||
const char* buf = _header->region_addr(i);
|
||||
const char* buf = region_addr(i);
|
||||
int crc = ClassLoader::crc32(0, buf, (jint)sz);
|
||||
if (crc != space_at(i)->_crc) {
|
||||
fail_continue("Checksum verification failed.");
|
||||
@ -1057,7 +1186,7 @@ void FileMapInfo::unmap_region(int i) {
|
||||
return;
|
||||
}
|
||||
|
||||
char* addr = _header->region_addr(i);
|
||||
char* addr = region_addr(i);
|
||||
if (!os::unmap_memory(addr, size)) {
|
||||
fail_stop("Unable to unmap shared space.");
|
||||
}
|
||||
@ -1078,6 +1207,7 @@ void FileMapInfo::metaspace_pointers_do(MetaspaceClosure* it) {
|
||||
|
||||
|
||||
FileMapInfo* FileMapInfo::_current_info = NULL;
|
||||
bool FileMapInfo::_heap_pointers_need_patching = false;
|
||||
Array<u8>* FileMapInfo::_shared_path_table = NULL;
|
||||
int FileMapInfo::_shared_path_table_size = 0;
|
||||
size_t FileMapInfo::_shared_path_entry_size = 0x1234baad;
|
||||
@ -1107,12 +1237,14 @@ bool FileMapInfo::initialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
char* FileMapHeader::region_addr(int idx) {
|
||||
char* FileMapInfo::region_addr(int idx) {
|
||||
CDSFileMapRegion* si = space_at(idx);
|
||||
if (MetaspaceShared::is_heap_region(idx)) {
|
||||
return _space[idx]._used > 0 ?
|
||||
(char*)((void*)CompressedOops::decode_not_null((narrowOop)_space[idx]._addr._offset)) : NULL;
|
||||
assert(DumpSharedSpaces, "The following doesn't work at runtime");
|
||||
return si->_used > 0 ?
|
||||
(char*)start_address_with_current_oop_encoding_mode(si) : NULL;
|
||||
} else {
|
||||
return _space[idx]._addr._base;
|
||||
return si->_addr._base;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1216,34 +1348,25 @@ bool FileMapInfo::is_in_shared_region(const void* p, int idx) {
|
||||
idx == MetaspaceShared::rw ||
|
||||
idx == MetaspaceShared::mc ||
|
||||
idx == MetaspaceShared::md, "invalid region index");
|
||||
char* base = _header->region_addr(idx);
|
||||
char* base = region_addr(idx);
|
||||
if (p >= base && p < base + space_at(idx)->_used) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FileMapInfo::print_shared_spaces() {
|
||||
tty->print_cr("Shared Spaces:");
|
||||
for (int i = 0; i < MetaspaceShared::n_regions; i++) {
|
||||
CDSFileMapRegion* si = space_at(i);
|
||||
char *base = _header->region_addr(i);
|
||||
tty->print(" %s " INTPTR_FORMAT "-" INTPTR_FORMAT,
|
||||
shared_region_name[i],
|
||||
p2i(base), p2i(base + si->_used));
|
||||
}
|
||||
}
|
||||
|
||||
// Unmap mapped regions of shared space.
|
||||
void FileMapInfo::stop_sharing_and_unmap(const char* msg) {
|
||||
FileMapInfo *map_info = FileMapInfo::current_info();
|
||||
if (map_info) {
|
||||
map_info->fail_continue("%s", msg);
|
||||
for (int i = 0; i < MetaspaceShared::num_non_heap_spaces; i++) {
|
||||
char *addr = map_info->_header->region_addr(i);
|
||||
if (addr != NULL && !MetaspaceShared::is_heap_region(i)) {
|
||||
map_info->unmap_region(i);
|
||||
map_info->space_at(i)->_addr._base = NULL;
|
||||
if (!MetaspaceShared::is_heap_region(i)) {
|
||||
char *addr = map_info->region_addr(i);
|
||||
if (addr != NULL) {
|
||||
map_info->unmap_region(i);
|
||||
map_info->space_at(i)->_addr._base = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Dealloc the archive heap regions only without unmapping. The regions are part
|
||||
|
@ -88,6 +88,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct ArchiveHeapOopmapInfo {
|
||||
address _oopmap; // bitmap for relocating embedded oops
|
||||
size_t _oopmap_size_in_bits;
|
||||
};
|
||||
|
||||
struct FileMapHeader : public CDSFileMapHeaderBase {
|
||||
size_t _alignment; // how shared archive should be aligned
|
||||
int _obj_alignment; // value of ObjectAlignmentInBytes
|
||||
@ -104,6 +109,7 @@ struct FileMapHeader : public CDSFileMapHeaderBase {
|
||||
size_t _cds_i2i_entry_code_buffers_size;
|
||||
size_t _core_spaces_size; // number of bytes allocated by the core spaces
|
||||
// (mc, md, ro, rw and od).
|
||||
MemRegion _heap_reserved; // reserved region for the entire heap at dump time.
|
||||
|
||||
// The following fields are all sanity checks for whether this archive
|
||||
// will function correctly with this JVM and the bootclasspath it's
|
||||
@ -152,13 +158,15 @@ struct FileMapHeader : public CDSFileMapHeaderBase {
|
||||
jshort max_used_path_index() { return _max_used_path_index; }
|
||||
jshort app_module_paths_start_index() { return _app_module_paths_start_index; }
|
||||
|
||||
char* region_addr(int idx);
|
||||
|
||||
bool validate();
|
||||
void populate(FileMapInfo* info, size_t alignment);
|
||||
int compute_crc();
|
||||
};
|
||||
|
||||
CDSFileMapRegion* space_at(int i) {
|
||||
assert(i >= 0 && i < NUM_CDS_REGIONS, "invalid region");
|
||||
return &_space[i];
|
||||
}
|
||||
};
|
||||
|
||||
class FileMapInfo : public CHeapObj<mtInternal> {
|
||||
private:
|
||||
@ -194,6 +202,7 @@ public:
|
||||
char* _paths_misc_info;
|
||||
|
||||
static FileMapInfo* _current_info;
|
||||
static bool _heap_pointers_need_patching;
|
||||
|
||||
bool init_from_file(int fd);
|
||||
void align_file_position();
|
||||
@ -253,12 +262,19 @@ public:
|
||||
void write_region(int region, char* base, size_t size,
|
||||
bool read_only, bool allow_exec);
|
||||
size_t write_archive_heap_regions(GrowableArray<MemRegion> *heap_mem,
|
||||
GrowableArray<ArchiveHeapOopmapInfo> *oopmaps,
|
||||
int first_region_id, int max_num_regions);
|
||||
void write_bytes(const void* buffer, size_t count);
|
||||
void write_bytes_aligned(const void* buffer, size_t count);
|
||||
char* map_region(int i, char** top_ret);
|
||||
void map_heap_regions_impl() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
void map_heap_regions() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
void fixup_mapped_heap_regions() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
void patch_archived_heap_embedded_pointers() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
void patch_archived_heap_embedded_pointers(MemRegion* ranges, int num_ranges,
|
||||
int first_region_idx) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
bool has_heap_regions() NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
MemRegion get_heap_regions_range_with_current_oop_encoding_mode() NOT_CDS_JAVA_HEAP_RETURN_(MemRegion());
|
||||
void unmap_region(int i);
|
||||
bool verify_region_checksum(int i);
|
||||
void close();
|
||||
@ -274,7 +290,6 @@ public:
|
||||
static void fail_continue(const char *msg, ...) ATTRIBUTE_PRINTF(1, 2);
|
||||
|
||||
bool is_in_shared_region(const void* p, int idx) NOT_CDS_RETURN_(false);
|
||||
void print_shared_spaces() NOT_CDS_RETURN;
|
||||
|
||||
// Stop CDS sharing and unmap CDS regions.
|
||||
static void stop_sharing_and_unmap(const char* msg);
|
||||
@ -303,6 +318,8 @@ public:
|
||||
return _shared_path_table_size;
|
||||
}
|
||||
|
||||
char* region_addr(int idx);
|
||||
|
||||
private:
|
||||
bool map_heap_data(MemRegion **heap_mem, int first, int max, int* num,
|
||||
bool is_open = false) NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
@ -310,9 +327,24 @@ public:
|
||||
void dealloc_archive_heap_regions(MemRegion* regions, int num) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
CDSFileMapRegion* space_at(int i) {
|
||||
assert(i >= 0 && i < NUM_CDS_REGIONS, "invalid region");
|
||||
return &_header->_space[i];
|
||||
return _header->space_at(i);
|
||||
}
|
||||
|
||||
narrowOop offset_of_space(CDSFileMapRegion* spc) {
|
||||
return (narrowOop)(spc->_addr._offset);
|
||||
}
|
||||
|
||||
// The starting address of spc, as calculated with CompressedOop::decode_non_null()
|
||||
address start_address_with_current_oop_encoding_mode(CDSFileMapRegion* spc) {
|
||||
return decode_start_address(spc, true);
|
||||
}
|
||||
|
||||
// The starting address of spc, as calculated with HeapShared::decode_with_archived_oop_encoding_mode()
|
||||
address start_address_with_archived_oop_encoding_mode(CDSFileMapRegion* spc) {
|
||||
return decode_start_address(spc, false);
|
||||
}
|
||||
|
||||
address decode_start_address(CDSFileMapRegion* spc, bool with_current_oop_encoding_mode);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_MEMORY_FILEMAP_HPP
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logMessage.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
#include "memory/heapShared.hpp"
|
||||
#include "memory/heapShared.inline.hpp"
|
||||
#include "memory/iterator.inline.hpp"
|
||||
#include "memory/metadataFactory.hpp"
|
||||
#include "memory/metaspaceClosure.hpp"
|
||||
@ -38,6 +38,7 @@
|
||||
#include "oops/compressedOops.inline.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/fieldDescriptor.inline.hpp"
|
||||
#include "utilities/bitMap.inline.hpp"
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
KlassSubGraphInfo* HeapShared::_subgraph_info_list = NULL;
|
||||
@ -72,6 +73,9 @@ KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) {
|
||||
return info;
|
||||
}
|
||||
|
||||
address HeapShared::_narrow_oop_base;
|
||||
int HeapShared::_narrow_oop_shift;
|
||||
|
||||
int HeapShared::num_of_subgraph_infos() {
|
||||
int num = 0;
|
||||
KlassSubGraphInfo* info = _subgraph_info_list;
|
||||
@ -320,7 +324,7 @@ void HeapShared::initialize_from_archived_subgraph(Klass* k) {
|
||||
// point. All objects in the subgraph reachable from the object are
|
||||
// also 'known' by GC.
|
||||
oop v = MetaspaceShared::materialize_archived_object(
|
||||
CompressedOops::decode(entry_field_records->at(i+1)));
|
||||
entry_field_records->at(i+1));
|
||||
m->obj_field_put(field_offset, v);
|
||||
i += 2;
|
||||
}
|
||||
@ -601,4 +605,96 @@ void HeapShared::archive_module_graph_objects(Thread* THREAD) {
|
||||
archive_reachable_objects_from_static_field(info->klass, info->offset, info->type, CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
// At dump-time, find the location of all the non-null oop pointers in an archived heap
|
||||
// region. This way we can quickly relocate all the pointers without using
|
||||
// BasicOopIterateClosure at runtime.
|
||||
class FindEmbeddedNonNullPointers: public BasicOopIterateClosure {
|
||||
narrowOop* _start;
|
||||
BitMap *_oopmap;
|
||||
int _num_total_oops;
|
||||
int _num_null_oops;
|
||||
public:
|
||||
FindEmbeddedNonNullPointers(narrowOop* start, BitMap* oopmap)
|
||||
: _start(start), _oopmap(oopmap), _num_total_oops(0), _num_null_oops(0) {}
|
||||
|
||||
virtual bool should_verify_oops(void) {
|
||||
return false;
|
||||
}
|
||||
virtual void do_oop(narrowOop* p) {
|
||||
_num_total_oops ++;
|
||||
narrowOop v = *p;
|
||||
if (!CompressedOops::is_null(v)) {
|
||||
size_t idx = p - _start;
|
||||
_oopmap->set_bit(idx);
|
||||
} else {
|
||||
_num_null_oops ++;
|
||||
}
|
||||
}
|
||||
virtual void do_oop(oop *p) {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
int num_total_oops() const { return _num_total_oops; }
|
||||
int num_null_oops() const { return _num_null_oops; }
|
||||
};
|
||||
|
||||
ResourceBitMap HeapShared::calculate_oopmap(MemRegion region) {
|
||||
assert(UseCompressedOops, "must be");
|
||||
size_t num_bits = region.byte_size() / sizeof(narrowOop);
|
||||
ResourceBitMap oopmap(num_bits);
|
||||
|
||||
HeapWord* p = region.start();
|
||||
HeapWord* end = region.end();
|
||||
FindEmbeddedNonNullPointers finder((narrowOop*)p, &oopmap);
|
||||
|
||||
int num_objs = 0;
|
||||
while (p < end) {
|
||||
oop o = (oop)p;
|
||||
o->oop_iterate(&finder);
|
||||
p += o->size();
|
||||
++ num_objs;
|
||||
}
|
||||
|
||||
log_info(cds, heap)("calculate_oopmap: objects = %6d, embedded oops = %7d, nulls = %7d",
|
||||
num_objs, finder.num_total_oops(), finder.num_null_oops());
|
||||
return oopmap;
|
||||
}
|
||||
|
||||
void HeapShared::init_narrow_oop_decoding(address base, int shift) {
|
||||
_narrow_oop_base = base;
|
||||
_narrow_oop_shift = shift;
|
||||
}
|
||||
|
||||
// Patch all the embedded oop pointers inside an archived heap region,
|
||||
// to be consistent with the runtime oop encoding.
|
||||
class PatchEmbeddedPointers: public BitMapClosure {
|
||||
narrowOop* _start;
|
||||
|
||||
public:
|
||||
PatchEmbeddedPointers(narrowOop* start) : _start(start) {}
|
||||
|
||||
bool do_bit(size_t offset) {
|
||||
narrowOop* p = _start + offset;
|
||||
narrowOop v = *p;
|
||||
assert(!CompressedOops::is_null(v), "null oops should have been filtered out at dump time");
|
||||
oop o = HeapShared::decode_with_archived_oop_encoding_mode(v);
|
||||
RawAccess<IS_NOT_NULL>::oop_store(p, o);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void HeapShared::patch_archived_heap_embedded_pointers(MemRegion region, address oopmap,
|
||||
size_t oopmap_size_in_bits) {
|
||||
BitMapView bm((BitMap::bm_word_t*)oopmap, oopmap_size_in_bits);
|
||||
|
||||
#ifndef PRODUCT
|
||||
ResourceMark rm;
|
||||
ResourceBitMap checkBm = calculate_oopmap(region);
|
||||
assert(bm.is_same(checkBm), "sanity");
|
||||
#endif
|
||||
|
||||
PatchEmbeddedPointers patcher((narrowOop*)region.start());
|
||||
bm.iterate(&patcher);
|
||||
}
|
||||
|
||||
#endif // INCLUDE_CDS_JAVA_HEAP
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "oops/objArrayKlass.hpp"
|
||||
#include "oops/oop.hpp"
|
||||
#include "oops/typeArrayKlass.hpp"
|
||||
#include "utilities/bitMap.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
@ -123,13 +124,33 @@ class HeapShared: AllStatic {
|
||||
static int num_of_subgraph_infos();
|
||||
|
||||
static size_t build_archived_subgraph_info_records(int num_records);
|
||||
|
||||
// Used by decode_with_archived_oop_encoding_mode
|
||||
static address _narrow_oop_base;
|
||||
static int _narrow_oop_shift;
|
||||
|
||||
#endif // INCLUDE_CDS_JAVA_HEAP
|
||||
public:
|
||||
static char* read_archived_subgraph_infos(char* buffer) NOT_CDS_JAVA_HEAP_RETURN_(buffer);
|
||||
static void write_archived_subgraph_infos() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void initialize_from_archived_subgraph(Klass* k) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
// NarrowOops stored in the CDS archive may use a different encoding scheme
|
||||
// than Universe::narrow_oop_{base,shift} -- see FileMapInfo::map_heap_regions_impl.
|
||||
// To decode them, do not use CompressedOops::decode_not_null. Use this
|
||||
// function instead.
|
||||
inline static oop decode_with_archived_oop_encoding_mode(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
|
||||
|
||||
static void init_narrow_oop_decoding(address base, int shift) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
static void patch_archived_heap_embedded_pointers(MemRegion mem, address oopmap,
|
||||
size_t oopmap_in_bits) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
static void init_archivable_static_fields(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void archive_module_graph_objects(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
static ResourceBitMap calculate_oopmap(MemRegion region);
|
||||
#endif
|
||||
};
|
||||
#endif // SHARE_VM_MEMORY_HEAPSHARED_HPP
|
||||
|
42
src/hotspot/share/memory/heapShared.inline.hpp
Normal file
42
src/hotspot/share/memory/heapShared.inline.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_MEMORY_HEAPSHARED_INLINE_HPP
|
||||
#define SHARE_VM_MEMORY_HEAPSHARED_INLINE_HPP
|
||||
|
||||
#include "oops/compressedOops.inline.hpp"
|
||||
#include "memory/heapShared.hpp"
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
|
||||
inline oop HeapShared::decode_with_archived_oop_encoding_mode(narrowOop v) {
|
||||
assert(!CompressedOops::is_null(v), "narrow oop value can never be zero");
|
||||
oop result = (oop)(void*)((uintptr_t)_narrow_oop_base + ((uintptr_t)v << _narrow_oop_shift));
|
||||
assert(check_obj_alignment(result), "address not aligned: " INTPTR_FORMAT, p2i((void*) result));
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // SHARE_VM_MEMORY_HEAPSHARED_INLINE_HPP
|
@ -39,7 +39,7 @@
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logMessage.hpp"
|
||||
#include "memory/filemap.hpp"
|
||||
#include "memory/heapShared.hpp"
|
||||
#include "memory/heapShared.inline.hpp"
|
||||
#include "memory/metaspace.hpp"
|
||||
#include "memory/metaspaceClosure.hpp"
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
@ -61,6 +61,7 @@
|
||||
#include "runtime/vmThread.hpp"
|
||||
#include "runtime/vm_operations.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/bitMap.hpp"
|
||||
#include "utilities/defaultStream.hpp"
|
||||
#include "utilities/hashtable.inline.hpp"
|
||||
#if INCLUDE_G1GC
|
||||
@ -227,7 +228,7 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
|
||||
// Map in spaces now also
|
||||
if (mapinfo->initialize() && map_shared_spaces(mapinfo)) {
|
||||
size_t cds_total = core_spaces_size();
|
||||
cds_address = (address)mapinfo->header()->region_addr(0);
|
||||
cds_address = (address)mapinfo->region_addr(0);
|
||||
#ifdef _LP64
|
||||
if (Metaspace::using_class_space()) {
|
||||
char* cds_end = (char*)(cds_address + cds_total);
|
||||
@ -309,10 +310,10 @@ void MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() {
|
||||
Universe::set_narrow_klass_range(cds_total);
|
||||
|
||||
Metaspace::initialize_class_space(tmp_class_space);
|
||||
tty->print_cr("narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
|
||||
log_info(cds)("narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
|
||||
p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift());
|
||||
|
||||
tty->print_cr("Allocated temporary class space: " SIZE_FORMAT " bytes at " PTR_FORMAT,
|
||||
log_info(cds)("Allocated temporary class space: " SIZE_FORMAT " bytes at " PTR_FORMAT,
|
||||
CompressedClassSpaceSize, p2i(tmp_class_space.base()));
|
||||
#endif
|
||||
|
||||
@ -424,6 +425,7 @@ void MetaspaceShared::serialize(SerializeClosure* soc) {
|
||||
soc->do_tag(--tag);
|
||||
|
||||
JavaClasses::serialize_offsets(soc);
|
||||
InstanceMirrorKlass::serialize_offsets(soc);
|
||||
soc->do_tag(--tag);
|
||||
|
||||
soc->do_tag(666);
|
||||
@ -1017,7 +1019,13 @@ private:
|
||||
GrowableArray<MemRegion> *_closed_archive_heap_regions;
|
||||
GrowableArray<MemRegion> *_open_archive_heap_regions;
|
||||
|
||||
GrowableArray<ArchiveHeapOopmapInfo> *_closed_archive_heap_oopmaps;
|
||||
GrowableArray<ArchiveHeapOopmapInfo> *_open_archive_heap_oopmaps;
|
||||
|
||||
void dump_java_heap_objects() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
void dump_archive_heap_oopmaps() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
void dump_archive_heap_oopmaps(GrowableArray<MemRegion>* regions,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* oopmaps);
|
||||
void dump_symbols();
|
||||
char* dump_read_only_tables();
|
||||
void print_region_stats();
|
||||
@ -1329,6 +1337,9 @@ char* VM_PopulateDumpSharedSpace::dump_read_only_tables() {
|
||||
WriteClosure wc(&_ro_region);
|
||||
MetaspaceShared::serialize(&wc);
|
||||
|
||||
// Write the bitmaps for patching the archive heap regions
|
||||
dump_archive_heap_oopmaps();
|
||||
|
||||
char* newtop = _ro_region.top();
|
||||
ArchiveCompactor::alloc_stats()->record_other_type(int(newtop - oldtop), true);
|
||||
return buckets_top;
|
||||
@ -1471,10 +1482,12 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||
|
||||
_total_string_region_size = mapinfo->write_archive_heap_regions(
|
||||
_closed_archive_heap_regions,
|
||||
_closed_archive_heap_oopmaps,
|
||||
MetaspaceShared::first_string,
|
||||
MetaspaceShared::max_strings);
|
||||
_total_open_archive_region_size = mapinfo->write_archive_heap_regions(
|
||||
_open_archive_heap_regions,
|
||||
_open_archive_heap_oopmaps,
|
||||
MetaspaceShared::first_open_archive_heap_region,
|
||||
MetaspaceShared::max_open_archive_heap_region);
|
||||
}
|
||||
@ -1810,6 +1823,36 @@ void VM_PopulateDumpSharedSpace::dump_java_heap_objects() {
|
||||
G1HeapVerifier::verify_archive_regions();
|
||||
}
|
||||
|
||||
void VM_PopulateDumpSharedSpace::dump_archive_heap_oopmaps() {
|
||||
if (MetaspaceShared::is_heap_object_archiving_allowed()) {
|
||||
_closed_archive_heap_oopmaps = new GrowableArray<ArchiveHeapOopmapInfo>(2);
|
||||
dump_archive_heap_oopmaps(_closed_archive_heap_regions, _closed_archive_heap_oopmaps);
|
||||
|
||||
_open_archive_heap_oopmaps = new GrowableArray<ArchiveHeapOopmapInfo>(2);
|
||||
dump_archive_heap_oopmaps(_open_archive_heap_regions, _open_archive_heap_oopmaps);
|
||||
}
|
||||
}
|
||||
|
||||
void VM_PopulateDumpSharedSpace::dump_archive_heap_oopmaps(GrowableArray<MemRegion>* regions,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* oopmaps) {
|
||||
for (int i=0; i<regions->length(); i++) {
|
||||
ResourceBitMap oopmap = HeapShared::calculate_oopmap(regions->at(i));
|
||||
size_t size_in_bits = oopmap.size();
|
||||
size_t size_in_bytes = oopmap.size_in_bytes();
|
||||
uintptr_t* buffer = (uintptr_t*)_ro_region.allocate(size_in_bytes, sizeof(intptr_t));
|
||||
oopmap.write_to(buffer, size_in_bytes);
|
||||
log_info(cds)("Oopmap = " INTPTR_FORMAT " (" SIZE_FORMAT_W(6) " bytes) for heap region "
|
||||
INTPTR_FORMAT " (" SIZE_FORMAT_W(8) " bytes)",
|
||||
p2i(buffer), size_in_bytes,
|
||||
p2i(regions->at(i).start()), regions->at(i).byte_size());
|
||||
|
||||
ArchiveHeapOopmapInfo info;
|
||||
info._oopmap = (address)buffer;
|
||||
info._oopmap_size_in_bits = size_in_bits;
|
||||
oopmaps->append(info);
|
||||
}
|
||||
}
|
||||
|
||||
void MetaspaceShared::dump_closed_archive_heap_objects(
|
||||
GrowableArray<MemRegion> * closed_archive) {
|
||||
assert(is_heap_object_archiving_allowed(), "Cannot dump java heap objects");
|
||||
@ -1896,8 +1939,9 @@ oop MetaspaceShared::archive_heap_object(oop obj, Thread* THREAD) {
|
||||
return archived_oop;
|
||||
}
|
||||
|
||||
oop MetaspaceShared::materialize_archived_object(oop obj) {
|
||||
if (obj != NULL) {
|
||||
oop MetaspaceShared::materialize_archived_object(narrowOop v) {
|
||||
if (!CompressedOops::is_null(v)) {
|
||||
oop obj = HeapShared::decode_with_archived_oop_encoding_mode(v);
|
||||
return G1CollectedHeap::heap()->materialize_archived_object(obj);
|
||||
}
|
||||
return NULL;
|
||||
@ -1973,7 +2017,7 @@ public:
|
||||
"Archived heap object is not allowed");
|
||||
assert(MetaspaceShared::open_archive_heap_region_mapped(),
|
||||
"Open archive heap region is not mapped");
|
||||
*p = CompressedOops::decode_not_null(o);
|
||||
*p = HeapShared::decode_with_archived_oop_encoding_mode(o);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2003,13 +2047,6 @@ bool MetaspaceShared::is_in_trampoline_frame(address addr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void MetaspaceShared::print_shared_spaces() {
|
||||
if (UseSharedSpaces) {
|
||||
FileMapInfo::current_info()->print_shared_spaces();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Map shared spaces at requested addresses and return if succeeded.
|
||||
bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
|
||||
size_t image_alignment = mapinfo->alignment();
|
||||
@ -2120,6 +2157,8 @@ void MetaspaceShared::initialize_shared_spaces() {
|
||||
// Initialize the run-time symbol table.
|
||||
SymbolTable::create_table();
|
||||
|
||||
mapinfo->patch_archived_heap_embedded_pointers();
|
||||
|
||||
// Close the mapinfo file
|
||||
mapinfo->close();
|
||||
|
||||
|
@ -79,6 +79,7 @@ class MetaspaceShared : AllStatic {
|
||||
// mapped java heap regions
|
||||
first_string = od + 1, // index of first string region
|
||||
max_strings = 2, // max number of string regions in string space
|
||||
last_string = first_string + max_strings - 1,
|
||||
first_open_archive_heap_region = first_string + max_strings,
|
||||
max_open_archive_heap_region = 2,
|
||||
|
||||
@ -111,7 +112,7 @@ class MetaspaceShared : AllStatic {
|
||||
}
|
||||
static oop find_archived_heap_object(oop obj);
|
||||
static oop archive_heap_object(oop obj, Thread* THREAD);
|
||||
static oop materialize_archived_object(oop obj);
|
||||
static oop materialize_archived_object(narrowOop v);
|
||||
static void archive_klass_objects(Thread* THREAD);
|
||||
#endif
|
||||
|
||||
@ -221,8 +222,6 @@ class MetaspaceShared : AllStatic {
|
||||
NOT_CDS(return false);
|
||||
}
|
||||
|
||||
static void print_shared_spaces();
|
||||
|
||||
static bool try_link_class(InstanceKlass* ik, TRAPS);
|
||||
static void link_and_cleanup_shared_classes(TRAPS);
|
||||
static void check_shared_class_loader_type(InstanceKlass* ik);
|
||||
|
@ -517,8 +517,11 @@ void Universe::fixup_mirrors(TRAPS) {
|
||||
// that the number of objects allocated at this point is very small.
|
||||
assert(SystemDictionary::Class_klass_loaded(), "java.lang.Class should be loaded");
|
||||
HandleMark hm(THREAD);
|
||||
// Cache the start of the static fields
|
||||
InstanceMirrorKlass::init_offset_of_static_fields();
|
||||
|
||||
if (!UseSharedSpaces) {
|
||||
// Cache the start of the static fields
|
||||
InstanceMirrorKlass::init_offset_of_static_fields();
|
||||
}
|
||||
|
||||
GrowableArray <Klass*>* list = java_lang_Class::fixup_mirror_list();
|
||||
int list_length = list->length();
|
||||
|
@ -777,7 +777,7 @@ oop ConstantPoolCache::archived_references() {
|
||||
if (CompressedOops::is_null(_archived_references)) {
|
||||
return NULL;
|
||||
}
|
||||
return MetaspaceShared::materialize_archived_object(CompressedOops::decode_not_null(_archived_references));
|
||||
return MetaspaceShared::materialize_archived_object(_archived_references);
|
||||
}
|
||||
|
||||
void ConstantPoolCache::set_archived_references(oop o) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2018, 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
|
||||
@ -66,3 +66,9 @@ int InstanceMirrorKlass::compute_static_oop_field_count(oop obj) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void InstanceMirrorKlass::serialize_offsets(SerializeClosure* f) {
|
||||
f->do_u4((u4*)&_offset_of_static_fields);
|
||||
}
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2018, 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
|
||||
@ -99,6 +99,8 @@ class InstanceMirrorKlass: public InstanceKlass {
|
||||
void oop_pc_update_pointers(oop obj, ParCompactionManager* cm);
|
||||
#endif
|
||||
|
||||
static void serialize_offsets(class SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Oop fields (and metadata) iterators
|
||||
//
|
||||
// The InstanceMirrorKlass iterators also visit the hidden Klass pointer.
|
||||
|
@ -571,6 +571,11 @@ oop Klass::archived_java_mirror_raw() {
|
||||
return CompressedOops::decode(_archived_mirror);
|
||||
}
|
||||
|
||||
narrowOop Klass::archived_java_mirror_raw_narrow() {
|
||||
assert(has_raw_archived_mirror(), "must have raw archived mirror");
|
||||
return _archived_mirror;
|
||||
}
|
||||
|
||||
// No GC barrier
|
||||
void Klass::set_archived_java_mirror_raw(oop m) {
|
||||
assert(DumpSharedSpaces, "called only during runtime");
|
||||
|
@ -261,6 +261,7 @@ protected:
|
||||
void set_java_mirror(Handle m);
|
||||
|
||||
oop archived_java_mirror_raw() NOT_CDS_JAVA_HEAP_RETURN_(NULL); // no GC barrier
|
||||
narrowOop archived_java_mirror_raw_narrow() NOT_CDS_JAVA_HEAP_RETURN_(0); // no GC barrier
|
||||
void set_archived_java_mirror_raw(oop m) NOT_CDS_JAVA_HEAP_RETURN; // no GC barrier
|
||||
|
||||
// Temporary mirror switch used by RedefineClasses
|
||||
|
@ -1585,7 +1585,7 @@ static void no_shared_spaces(const char* message) {
|
||||
if (RequireSharedSpaces) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"Class data sharing is inconsistent with other specified options.\n");
|
||||
vm_exit_during_initialization("Unable to use shared archive.", message);
|
||||
vm_exit_during_initialization("Unable to use shared archive", message);
|
||||
} else {
|
||||
FLAG_SET_DEFAULT(UseSharedSpaces, false);
|
||||
}
|
||||
|
@ -672,6 +672,11 @@ void BitMap::print_on_error(outputStream* st, const char* prefix) const {
|
||||
prefix, p2i(map()), p2i((char*)map() + (size() >> LogBitsPerByte)));
|
||||
}
|
||||
|
||||
void BitMap::write_to(bm_word_t* buffer, size_t buffer_size_in_bytes) const {
|
||||
assert(buffer_size_in_bytes == size_in_bytes(), "must be");
|
||||
memcpy(buffer, _map, size_in_bytes());
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
||||
void BitMap::print_on(outputStream* st) const {
|
||||
|
@ -288,6 +288,7 @@ class BitMap {
|
||||
bool is_full() const;
|
||||
bool is_empty() const;
|
||||
|
||||
void write_to(bm_word_t* buffer, size_t buffer_size_in_bytes) const;
|
||||
void print_on_error(outputStream* st, const char* prefix) const;
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 automatic relocation of archive heap regions dur to heap size changes.
|
||||
* @requires vm.cds.archived.java.heap
|
||||
* @requires (vm.gc=="null")
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
|
||||
* @modules jdk.jartool/sun.tools.jar
|
||||
* @compile ../test-classes/Hello.java
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. DifferentHeapSizes
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import sun.hotspot.WhiteBox;
|
||||
import jdk.test.lib.cds.CDSTestUtils;
|
||||
|
||||
public class DifferentHeapSizes {
|
||||
static class Scenario {
|
||||
int dumpSize; // in MB
|
||||
int runSizes[]; // in MB
|
||||
Scenario(int ds, int... rs) {
|
||||
dumpSize = ds;
|
||||
runSizes = rs;
|
||||
}
|
||||
}
|
||||
|
||||
static Scenario[] scenarios = {
|
||||
// dump -Xmx , run -Xmx
|
||||
new Scenario( 32, 32, 64, 512, 2048, 4097, 16374, 31000),
|
||||
new Scenario( 128, 32, 64, 512, 2048, 4097, 16374, 31000, 40000),
|
||||
new Scenario( 2048, 32, 512, 2600, 4097, 8500, 31000, 40000),
|
||||
new Scenario( 17000, 32, 512, 2048, 4097, 8500, 31000, 40000),
|
||||
new Scenario( 31000, 32, 512, 2048, 4097, 8500, 17000, 40000)
|
||||
};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String dedup = "-XX:+UseStringDeduplication"; // This increases code coverage.
|
||||
JarBuilder.getOrCreateHelloJar();
|
||||
String appJar = TestCommon.getTestJar("hello.jar");
|
||||
String appClasses[] = TestCommon.list("Hello");
|
||||
|
||||
for (Scenario s : scenarios) {
|
||||
String dumpXmx = "-Xmx" + s.dumpSize + "m";
|
||||
OutputAnalyzer output = TestCommon.dump(appJar, appClasses, dumpXmx);
|
||||
|
||||
for (int runSize : s.runSizes) {
|
||||
String runXmx = "-Xmx" + runSize + "m";
|
||||
CDSTestUtils.Result result = TestCommon.run("-cp", appJar, "-showversion",
|
||||
"-Xlog:cds", runXmx, dedup, "Hello");
|
||||
if (runSize < 32768) {
|
||||
result
|
||||
.assertNormalExit("Hello World")
|
||||
.assertNormalExit(out -> {
|
||||
out.shouldNotContain(CDSTestUtils.MSG_RANGE_NOT_WITHIN_HEAP);
|
||||
out.shouldNotContain(CDSTestUtils.MSG_RANGE_ALREADT_IN_USE);
|
||||
});
|
||||
} else {
|
||||
result.assertAbnormalExit("Unable to use shared archive: UseCompressedOops and UseCompressedClassPointers must be on for UseSharedSpaces.");
|
||||
}
|
||||
}
|
||||
}
|
||||
String flag = "HeapBaseMinAddress";
|
||||
String xxflag = "-XX:" + flag + "=";
|
||||
String mx = "-Xmx128m";
|
||||
long base = WhiteBox.getWhiteBox().getSizeTVMFlag(flag).longValue();
|
||||
|
||||
TestCommon.dump(appJar, appClasses, mx, xxflag + base);
|
||||
TestCommon.run("-cp", appJar, "-showversion", "-Xlog:cds", mx, xxflag + (base + 256 * 1024 * 1024), dedup, "Hello")
|
||||
.assertNormalExit("Hello World")
|
||||
.assertNormalExit(out -> {
|
||||
out.shouldNotContain(CDSTestUtils.MSG_RANGE_NOT_WITHIN_HEAP);
|
||||
out.shouldNotContain(CDSTestUtils.MSG_RANGE_ALREADT_IN_USE);
|
||||
});
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, 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 Shared classes can still be used when archived heap regions cannot be
|
||||
* mapped due to out of range, and -Xshare:on should not fail. Test on
|
||||
* linux 64-bit only since the HeapBaseMinAddress value is platform specific.
|
||||
* The value used in the test may cause different behavior on other platforms.
|
||||
* @requires vm.cds.archived.java.heap
|
||||
* @requires os.family == "linux"
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @modules java.management
|
||||
* jdk.jartool/sun.tools.jar
|
||||
* @compile ../test-classes/Hello.java
|
||||
* @run main RangeNotWithinHeap
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
public class RangeNotWithinHeap {
|
||||
public static void main(String[] args) throws Exception {
|
||||
JarBuilder.getOrCreateHelloJar();
|
||||
String appJar = TestCommon.getTestJar("hello.jar");
|
||||
String appClasses[] = TestCommon.list("Hello");
|
||||
|
||||
OutputAnalyzer output = TestCommon.dump(appJar, appClasses,
|
||||
"-XX:HeapBaseMinAddress=0x600000000", "-Xmx6G", "-Xlog:gc+heap=trace");
|
||||
TestCommon.checkDump(output, "oa0 space:");
|
||||
|
||||
// Force archive region out of runtime java heap
|
||||
output = TestCommon.exec(appJar, "Hello");
|
||||
TestCommon.checkExec(output, "Hello World");
|
||||
output = TestCommon.exec(appJar,
|
||||
"-XX:HeapBaseMinAddress=0x600000000", "-Xmx2G", "-Xlog:gc+heap=trace,cds", "Hello");
|
||||
TestCommon.checkExec(output, "Hello World");
|
||||
try {
|
||||
output.shouldContain(
|
||||
"UseSharedSpaces: Unable to allocate region, range is not within java heap.");
|
||||
} catch (Exception e) {
|
||||
// In rare case the heap data is not used.
|
||||
if (output.getOutput().contains("Cached heap data from the CDS archive is being ignored")) {
|
||||
return;
|
||||
}
|
||||
// Check for common shared class data mapping failures.
|
||||
TestCommon.checkCommonExecExceptions(output, e);
|
||||
}
|
||||
}
|
||||
}
|
@ -141,10 +141,10 @@ public class IncompatibleOptions {
|
||||
// main class param, and fails with "Could not find or load main class"
|
||||
if (!extraOption.isEmpty()) {
|
||||
output = TestCommon.exec(appJar, "-XX:+UseCompressedOops",
|
||||
collectorOption, extraOption, "HelloString");
|
||||
collectorOption, "-Xlog:cds", extraOption, "HelloString");
|
||||
} else {
|
||||
output = TestCommon.exec(appJar, "-XX:+UseCompressedOops",
|
||||
collectorOption, "HelloString");
|
||||
collectorOption, "-Xlog:cds", "HelloString");
|
||||
}
|
||||
|
||||
if (expectedWarning != null)
|
||||
|
@ -36,6 +36,11 @@ import jtreg.SkippedException;
|
||||
|
||||
// This class contains common test utilities for testing CDS
|
||||
public class CDSTestUtils {
|
||||
public static final String MSG_RANGE_NOT_WITHIN_HEAP =
|
||||
"UseSharedSpaces: Unable to allocate region, range is not within java heap.";
|
||||
public static final String MSG_RANGE_ALREADT_IN_USE =
|
||||
"Unable to allocate region, java heap range is already in use.";
|
||||
|
||||
public interface Checker {
|
||||
public void check(OutputAnalyzer output) throws Exception;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user