mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-18 10:04:42 +02:00
8273508: Support archived heap objects in SerialGC
Reviewed-by: tschatzl, ccheung
This commit is contained in:
parent
3eca9c36a6
commit
6a573b888d
13 changed files with 211 additions and 33 deletions
|
@ -1597,8 +1597,9 @@ MapArchiveResult FileMapInfo::map_regions(int regions[], int num_regions, char*
|
||||||
return MAP_ARCHIVE_SUCCESS;
|
return MAP_ARCHIVE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileMapInfo::read_region(int i, char* base, size_t size) {
|
bool FileMapInfo::read_region(int i, char* base, size_t size, bool do_commit) {
|
||||||
FileMapRegion* si = space_at(i);
|
FileMapRegion* si = space_at(i);
|
||||||
|
if (do_commit) {
|
||||||
log_info(cds)("Commit %s region #%d at base " INTPTR_FORMAT " top " INTPTR_FORMAT " (%s)%s",
|
log_info(cds)("Commit %s region #%d at base " INTPTR_FORMAT " top " INTPTR_FORMAT " (%s)%s",
|
||||||
is_static() ? "static " : "dynamic", i, p2i(base), p2i(base + size),
|
is_static() ? "static " : "dynamic", i, p2i(base), p2i(base + size),
|
||||||
shared_region_name[i], si->allow_exec() ? " exec" : "");
|
shared_region_name[i], si->allow_exec() ? " exec" : "");
|
||||||
|
@ -1607,6 +1608,7 @@ bool FileMapInfo::read_region(int i, char* base, size_t size) {
|
||||||
i, shared_region_name[i]);
|
i, shared_region_name[i]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (lseek(_fd, (long)si->file_offset(), SEEK_SET) != (int)si->file_offset() ||
|
if (lseek(_fd, (long)si->file_offset(), SEEK_SET) != (int)si->file_offset() ||
|
||||||
read_bytes(base, size) != size) {
|
read_bytes(base, size) != size) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1646,7 +1648,7 @@ MapArchiveResult FileMapInfo::map_region(int i, intx addr_delta, char* mapped_ba
|
||||||
// that covers all the FileMapRegions to ensure all regions can be mapped. However, Windows
|
// that covers all the FileMapRegions to ensure all regions can be mapped. However, Windows
|
||||||
// can't mmap into a ReservedSpace, so we just os::read() the data. We're going to patch all the
|
// can't mmap into a ReservedSpace, so we just os::read() the data. We're going to patch all the
|
||||||
// regions anyway, so there's no benefit for mmap anyway.
|
// regions anyway, so there's no benefit for mmap anyway.
|
||||||
if (!read_region(i, requested_addr, size)) {
|
if (!read_region(i, requested_addr, size, /* do_commit = */ true)) {
|
||||||
log_info(cds)("Failed to read %s shared space into reserved space at " INTPTR_FORMAT,
|
log_info(cds)("Failed to read %s shared space into reserved space at " INTPTR_FORMAT,
|
||||||
shared_region_name[i], p2i(requested_addr));
|
shared_region_name[i], p2i(requested_addr));
|
||||||
return MAP_ARCHIVE_OTHER_FAILURE; // oom or I/O error.
|
return MAP_ARCHIVE_OTHER_FAILURE; // oom or I/O error.
|
||||||
|
@ -1817,7 +1819,7 @@ void FileMapInfo::map_or_load_heap_regions() {
|
||||||
} else if (HeapShared::can_load()) {
|
} else if (HeapShared::can_load()) {
|
||||||
success = HeapShared::load_heap_regions(this);
|
success = HeapShared::load_heap_regions(this);
|
||||||
} else {
|
} else {
|
||||||
log_info(cds)("Cannot use CDS heap data. UseG1GC or UseEpsilonGC are required.");
|
log_info(cds)("Cannot use CDS heap data. UseEpsilonGC, UseG1GC or UseSerialGC are required.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -477,7 +477,7 @@ public:
|
||||||
int first_region_idx) NOT_CDS_JAVA_HEAP_RETURN;
|
int first_region_idx) NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
bool has_heap_regions() NOT_CDS_JAVA_HEAP_RETURN_(false);
|
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());
|
MemRegion get_heap_regions_range_with_current_oop_encoding_mode() NOT_CDS_JAVA_HEAP_RETURN_(MemRegion());
|
||||||
bool read_region(int i, char* base, size_t size);
|
bool read_region(int i, char* base, size_t size, bool do_commit);
|
||||||
char* map_bitmap_region();
|
char* map_bitmap_region();
|
||||||
void unmap_region(int i);
|
void unmap_region(int i);
|
||||||
bool verify_region_checksum(int i);
|
bool verify_region_checksum(int i);
|
||||||
|
|
|
@ -1586,7 +1586,7 @@ class PatchLoadedRegionPointers: public BitMapClosure {
|
||||||
};
|
};
|
||||||
|
|
||||||
int HeapShared::init_loaded_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_regions,
|
int HeapShared::init_loaded_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_regions,
|
||||||
uintptr_t* buffer_ret) {
|
MemRegion& archive_space) {
|
||||||
size_t total_bytes = 0;
|
size_t total_bytes = 0;
|
||||||
int num_loaded_regions = 0;
|
int num_loaded_regions = 0;
|
||||||
for (int i = MetaspaceShared::first_archive_heap_region;
|
for (int i = MetaspaceShared::first_archive_heap_region;
|
||||||
|
@ -1604,12 +1604,16 @@ int HeapShared::init_loaded_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegio
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(is_aligned(total_bytes, HeapWordSize), "must be");
|
assert(is_aligned(total_bytes, HeapWordSize), "must be");
|
||||||
uintptr_t buffer = (uintptr_t)
|
size_t word_size = total_bytes / HeapWordSize;
|
||||||
Universe::heap()->allocate_loaded_archive_space(total_bytes / HeapWordSize);
|
HeapWord* buffer = Universe::heap()->allocate_loaded_archive_space(word_size);
|
||||||
_loaded_heap_bottom = buffer;
|
if (buffer == nullptr) {
|
||||||
_loaded_heap_top = buffer + total_bytes;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
archive_space = MemRegion(buffer, word_size);
|
||||||
|
_loaded_heap_bottom = (uintptr_t)archive_space.start();
|
||||||
|
_loaded_heap_top = _loaded_heap_bottom + total_bytes;
|
||||||
|
|
||||||
*buffer_ret = buffer;
|
|
||||||
return num_loaded_regions;
|
return num_loaded_regions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1638,15 +1642,17 @@ bool HeapShared::load_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loa
|
||||||
LoadedArchiveHeapRegion* ri = &loaded_regions[i];
|
LoadedArchiveHeapRegion* ri = &loaded_regions[i];
|
||||||
FileMapRegion* r = mapinfo->space_at(ri->_region_index);
|
FileMapRegion* r = mapinfo->space_at(ri->_region_index);
|
||||||
|
|
||||||
if (!mapinfo->read_region(ri->_region_index, (char*)load_address, r->used())) {
|
if (!mapinfo->read_region(ri->_region_index, (char*)load_address, r->used(), /* do_commit = */ false)) {
|
||||||
// There's no easy way to free the buffer, so we will fill it with zero later
|
// There's no easy way to free the buffer, so we will fill it with zero later
|
||||||
// in fill_failed_loaded_region(), and it will eventually be GC'ed.
|
// in fill_failed_loaded_region(), and it will eventually be GC'ed.
|
||||||
log_warning(cds)("Loading of heap region %d has failed. Archived objects are disabled", i);
|
log_warning(cds)("Loading of heap region %d has failed. Archived objects are disabled", i);
|
||||||
_loading_failed = true;
|
_loading_failed = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
log_info(cds)("Loaded heap region #%d at base " INTPTR_FORMAT " size = " SIZE_FORMAT_W(8) " bytes, delta = " INTX_FORMAT,
|
log_info(cds)("Loaded heap region #%d at base " INTPTR_FORMAT " top " INTPTR_FORMAT
|
||||||
ri->_region_index, load_address, ri->_region_size, ri->_runtime_offset);
|
" size " SIZE_FORMAT_W(6) " delta " INTX_FORMAT,
|
||||||
|
ri->_region_index, load_address, load_address + ri->_region_size,
|
||||||
|
ri->_region_size, ri->_runtime_offset);
|
||||||
|
|
||||||
uintptr_t oopmap = bitmap_base + r->oopmap_offset();
|
uintptr_t oopmap = bitmap_base + r->oopmap_offset();
|
||||||
BitMapView bm((BitMap::bm_word_t*)oopmap, r->oopmap_size_in_bits());
|
BitMapView bm((BitMap::bm_word_t*)oopmap, r->oopmap_size_in_bits());
|
||||||
|
@ -1675,10 +1681,14 @@ bool HeapShared::load_heap_regions(FileMapInfo* mapinfo) {
|
||||||
LoadedArchiveHeapRegion loaded_regions[MetaspaceShared::max_num_heap_regions];
|
LoadedArchiveHeapRegion loaded_regions[MetaspaceShared::max_num_heap_regions];
|
||||||
memset(loaded_regions, 0, sizeof(loaded_regions));
|
memset(loaded_regions, 0, sizeof(loaded_regions));
|
||||||
|
|
||||||
uintptr_t buffer;
|
MemRegion archive_space;
|
||||||
int num_loaded_regions = init_loaded_regions(mapinfo, loaded_regions, &buffer);
|
int num_loaded_regions = init_loaded_regions(mapinfo, loaded_regions, archive_space);
|
||||||
sort_loaded_regions(loaded_regions, num_loaded_regions, buffer);
|
if (num_loaded_regions <= 0) {
|
||||||
if (!load_regions(mapinfo, loaded_regions, num_loaded_regions, buffer)) {
|
return false;
|
||||||
|
}
|
||||||
|
sort_loaded_regions(loaded_regions, num_loaded_regions, (uintptr_t)archive_space.start());
|
||||||
|
if (!load_regions(mapinfo, loaded_regions, num_loaded_regions, (uintptr_t)archive_space.start())) {
|
||||||
|
assert(_loading_failed, "must be");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1711,7 +1721,15 @@ class VerifyLoadedHeapEmbeddedPointers: public BasicOopIterateClosure {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void HeapShared::verify_loaded_heap() {
|
void HeapShared::finish_initialization() {
|
||||||
|
if (is_loaded()) {
|
||||||
|
HeapWord* bottom = (HeapWord*)_loaded_heap_bottom;
|
||||||
|
HeapWord* top = (HeapWord*)_loaded_heap_top;
|
||||||
|
|
||||||
|
MemRegion archive_space = MemRegion(bottom, top);
|
||||||
|
Universe::heap()->complete_loaded_archive_space(archive_space);
|
||||||
|
}
|
||||||
|
|
||||||
if (VerifyArchivedFields <= 0 || !is_loaded()) {
|
if (VerifyArchivedFields <= 0 || !is_loaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1739,9 +1757,12 @@ void HeapShared::verify_loaded_heap() {
|
||||||
|
|
||||||
void HeapShared::fill_failed_loaded_region() {
|
void HeapShared::fill_failed_loaded_region() {
|
||||||
assert(_loading_failed, "must be");
|
assert(_loading_failed, "must be");
|
||||||
|
if (_loaded_heap_bottom != 0) {
|
||||||
|
assert(_loaded_heap_top != 0, "must be");
|
||||||
HeapWord* bottom = (HeapWord*)_loaded_heap_bottom;
|
HeapWord* bottom = (HeapWord*)_loaded_heap_bottom;
|
||||||
HeapWord* top = (HeapWord*)_loaded_heap_top;
|
HeapWord* top = (HeapWord*)_loaded_heap_top;
|
||||||
Universe::heap()->fill_with_objects(bottom, top - bottom);
|
Universe::heap()->fill_with_objects(bottom, top - bottom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // INCLUDE_CDS_JAVA_HEAP
|
#endif // INCLUDE_CDS_JAVA_HEAP
|
||||||
|
|
|
@ -170,7 +170,7 @@ public:
|
||||||
|
|
||||||
// Can this VM load the objects from archived heap regions into the heap at start-up?
|
// Can this VM load the objects from archived heap regions into the heap at start-up?
|
||||||
static bool can_load() NOT_CDS_JAVA_HEAP_RETURN_(false);
|
static bool can_load() NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||||
static void verify_loaded_heap() NOT_CDS_JAVA_HEAP_RETURN;
|
static void finish_initialization() NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
static bool is_loaded() {
|
static bool is_loaded() {
|
||||||
CDS_JAVA_HEAP_ONLY(return _is_loaded;)
|
CDS_JAVA_HEAP_ONLY(return _is_loaded;)
|
||||||
NOT_CDS_JAVA_HEAP(return false;)
|
NOT_CDS_JAVA_HEAP(return false;)
|
||||||
|
@ -346,7 +346,7 @@ private:
|
||||||
static void init_archived_fields_for(Klass* k, const ArchivedKlassSubGraphInfoRecord* record);
|
static void init_archived_fields_for(Klass* k, const ArchivedKlassSubGraphInfoRecord* record);
|
||||||
|
|
||||||
static int init_loaded_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_regions,
|
static int init_loaded_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_regions,
|
||||||
uintptr_t* buffer_ret);
|
MemRegion& archive_space);
|
||||||
static void sort_loaded_regions(LoadedArchiveHeapRegion* loaded_regions, int num_loaded_regions,
|
static void sort_loaded_regions(LoadedArchiveHeapRegion* loaded_regions, int num_loaded_regions,
|
||||||
uintptr_t buffer);
|
uintptr_t buffer);
|
||||||
static bool load_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_regions,
|
static bool load_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_regions,
|
||||||
|
|
|
@ -1434,7 +1434,7 @@ void MetaspaceShared::initialize_shared_spaces() {
|
||||||
// Finish up archived heap initialization. These must be
|
// Finish up archived heap initialization. These must be
|
||||||
// done after ReadClosure.
|
// done after ReadClosure.
|
||||||
static_mapinfo->patch_heap_embedded_pointers();
|
static_mapinfo->patch_heap_embedded_pointers();
|
||||||
HeapShared::verify_loaded_heap();
|
HeapShared::finish_initialization();
|
||||||
|
|
||||||
// Close the mapinfo file
|
// Close the mapinfo file
|
||||||
static_mapinfo->close();
|
static_mapinfo->close();
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "gc/shared/strongRootsScope.hpp"
|
#include "gc/shared/strongRootsScope.hpp"
|
||||||
#include "gc/shared/suspendibleThreadSet.hpp"
|
#include "gc/shared/suspendibleThreadSet.hpp"
|
||||||
#include "memory/universe.hpp"
|
#include "memory/universe.hpp"
|
||||||
|
#include "runtime/mutexLocker.hpp"
|
||||||
#include "services/memoryManager.hpp"
|
#include "services/memoryManager.hpp"
|
||||||
|
|
||||||
SerialHeap* SerialHeap::heap() {
|
SerialHeap* SerialHeap::heap() {
|
||||||
|
@ -112,3 +113,13 @@ void SerialHeap::safepoint_synchronize_end() {
|
||||||
SuspendibleThreadSet::desynchronize();
|
SuspendibleThreadSet::desynchronize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HeapWord* SerialHeap::allocate_loaded_archive_space(size_t word_size) {
|
||||||
|
MutexLocker ml(Heap_lock);
|
||||||
|
return old_gen()->allocate(word_size, false /* is_tlab */);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialHeap::complete_loaded_archive_space(MemRegion archive_space) {
|
||||||
|
assert(old_gen()->used_region().contains(archive_space), "Archive space not contained in old gen");
|
||||||
|
old_gen()->complete_loaded_archive_space(archive_space);
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2021, 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
|
||||||
|
@ -83,6 +83,11 @@ public:
|
||||||
|
|
||||||
virtual void safepoint_synchronize_begin();
|
virtual void safepoint_synchronize_begin();
|
||||||
virtual void safepoint_synchronize_end();
|
virtual void safepoint_synchronize_end();
|
||||||
|
|
||||||
|
// Support for loading objects from CDS archive into the heap
|
||||||
|
bool can_load_archived_objects() const { return true; }
|
||||||
|
HeapWord* allocate_loaded_archive_space(size_t size);
|
||||||
|
void complete_loaded_archive_space(MemRegion archive_space);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_GC_SERIAL_SERIALHEAP_HPP
|
#endif // SHARE_GC_SERIAL_SERIALHEAP_HPP
|
||||||
|
|
|
@ -219,6 +219,18 @@ void TenuredGeneration::object_iterate(ObjectClosure* blk) {
|
||||||
_the_space->object_iterate(blk);
|
_the_space->object_iterate(blk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TenuredGeneration::complete_loaded_archive_space(MemRegion archive_space) {
|
||||||
|
// Create the BOT for the archive space.
|
||||||
|
TenuredSpace* space = (TenuredSpace*)_the_space;
|
||||||
|
space->initialize_threshold();
|
||||||
|
HeapWord* start = archive_space.start();
|
||||||
|
while (start < archive_space.end()) {
|
||||||
|
size_t word_size = _the_space->block_size(start);
|
||||||
|
space->alloc_block(start, start + word_size);
|
||||||
|
start += word_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TenuredGeneration::save_marks() {
|
void TenuredGeneration::save_marks() {
|
||||||
_the_space->set_saved_mark();
|
_the_space->set_saved_mark();
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,8 @@ class TenuredGeneration: public CardGeneration {
|
||||||
// Iteration
|
// Iteration
|
||||||
void object_iterate(ObjectClosure* blk);
|
void object_iterate(ObjectClosure* blk);
|
||||||
|
|
||||||
|
void complete_loaded_archive_space(MemRegion archive_space);
|
||||||
|
|
||||||
virtual inline HeapWord* allocate(size_t word_size, bool is_tlab);
|
virtual inline HeapWord* allocate(size_t word_size, bool is_tlab);
|
||||||
virtual inline HeapWord* par_allocate(size_t word_size, bool is_tlab);
|
virtual inline HeapWord* par_allocate(size_t word_size, bool is_tlab);
|
||||||
|
|
||||||
|
|
|
@ -485,6 +485,7 @@ class CollectedHeap : public CHeapObj<mtInternal> {
|
||||||
// (usually as a snapshot of the old generation).
|
// (usually as a snapshot of the old generation).
|
||||||
virtual bool can_load_archived_objects() const { return false; }
|
virtual bool can_load_archived_objects() const { return false; }
|
||||||
virtual HeapWord* allocate_loaded_archive_space(size_t size) { return NULL; }
|
virtual HeapWord* allocate_loaded_archive_space(size_t size) { return NULL; }
|
||||||
|
virtual void complete_loaded_archive_space(MemRegion archive_space) { }
|
||||||
|
|
||||||
virtual bool is_oop(oop object) const;
|
virtual bool is_oop(oop object) const;
|
||||||
// Non product verification and debugging.
|
// Non product verification and debugging.
|
||||||
|
|
|
@ -367,8 +367,9 @@ hotspot_appcds_dynamic = \
|
||||||
-runtime/cds/appcds/SharedArchiveConsistency.java \
|
-runtime/cds/appcds/SharedArchiveConsistency.java \
|
||||||
-runtime/cds/appcds/StaticArchiveWithLambda.java \
|
-runtime/cds/appcds/StaticArchiveWithLambda.java \
|
||||||
-runtime/cds/appcds/TestCombinedCompressedFlags.java \
|
-runtime/cds/appcds/TestCombinedCompressedFlags.java \
|
||||||
-runtime/cds/appcds/TestZGCWithCDS.java \
|
|
||||||
-runtime/cds/appcds/TestEpsilonGCWithCDS.java \
|
-runtime/cds/appcds/TestEpsilonGCWithCDS.java \
|
||||||
|
-runtime/cds/appcds/TestSerialGCWithCDS.java \
|
||||||
|
-runtime/cds/appcds/TestZGCWithCDS.java \
|
||||||
-runtime/cds/appcds/UnusedCPDuringDump.java \
|
-runtime/cds/appcds/UnusedCPDuringDump.java \
|
||||||
-runtime/cds/appcds/VerifierTest_1B.java
|
-runtime/cds/appcds/VerifierTest_1B.java
|
||||||
|
|
||||||
|
|
122
test/hotspot/jtreg/runtime/cds/appcds/TestSerialGCWithCDS.java
Normal file
122
test/hotspot/jtreg/runtime/cds/appcds/TestSerialGCWithCDS.java
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, 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 Loading CDS archived heap objects into SerialGC
|
||||||
|
* @bug 8234679
|
||||||
|
* @requires vm.cds
|
||||||
|
* @requires vm.gc.Serial
|
||||||
|
* @requires vm.gc.G1
|
||||||
|
*
|
||||||
|
* @comment don't run this test if any -XX::+Use???GC options are specified, since they will
|
||||||
|
* interfere with the the test.
|
||||||
|
* @requires vm.gc == null
|
||||||
|
*
|
||||||
|
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
|
||||||
|
* @compile test-classes/Hello.java
|
||||||
|
* @run driver TestSerialGCWithCDS
|
||||||
|
*/
|
||||||
|
|
||||||
|
import jdk.test.lib.Platform;
|
||||||
|
import jdk.test.lib.process.OutputAnalyzer;
|
||||||
|
|
||||||
|
public class TestSerialGCWithCDS {
|
||||||
|
public final static String HELLO = "Hello World";
|
||||||
|
static String helloJar;
|
||||||
|
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
helloJar = JarBuilder.build("hello", "Hello");
|
||||||
|
|
||||||
|
// Check if we can use SerialGC during dump time, or run time, or both.
|
||||||
|
test(false, true);
|
||||||
|
test(true, false);
|
||||||
|
test(true, true);
|
||||||
|
|
||||||
|
// We usually have 2 heap regions. To increase test coverage, we can have 3 heap regions
|
||||||
|
// by using "-Xmx256m -XX:ObjectAlignmentInBytes=64"
|
||||||
|
if (Platform.is64bit()) test(false, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
final static String G1 = "-XX:+UseG1GC";
|
||||||
|
final static String Serial = "-XX:+UseSerialGC";
|
||||||
|
|
||||||
|
static void test(boolean dumpWithSerial, boolean execWithSerial) throws Exception {
|
||||||
|
test(dumpWithSerial, execWithSerial, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test(boolean dumpWithSerial, boolean execWithSerial, boolean useSmallRegions) throws Exception {
|
||||||
|
String dumpGC = dumpWithSerial ? Serial : G1;
|
||||||
|
String execGC = execWithSerial ? Serial : G1;
|
||||||
|
String small1 = useSmallRegions ? "-Xmx256m" : "-showversion";
|
||||||
|
String small2 = useSmallRegions ? "-XX:ObjectAlignmentInBytes=64" : "-showversion";
|
||||||
|
OutputAnalyzer out;
|
||||||
|
|
||||||
|
System.out.println("0. Dump with " + dumpGC);
|
||||||
|
out = TestCommon.dump(helloJar,
|
||||||
|
new String[] {"Hello"},
|
||||||
|
dumpGC,
|
||||||
|
small1,
|
||||||
|
small2,
|
||||||
|
"-Xlog:cds");
|
||||||
|
out.shouldContain("Dumping shared data to file:");
|
||||||
|
out.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
System.out.println("1. Exec with " + execGC);
|
||||||
|
out = TestCommon.exec(helloJar,
|
||||||
|
execGC,
|
||||||
|
small1,
|
||||||
|
small2,
|
||||||
|
"-Xlog:cds",
|
||||||
|
"Hello");
|
||||||
|
out.shouldContain(HELLO);
|
||||||
|
out.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
int n = 2;
|
||||||
|
if (dumpWithSerial == false && execWithSerial == true) {
|
||||||
|
// We dumped with G1, so we have an archived heap. At exec time, try to load them into
|
||||||
|
// a small SerialGC heap that may be too small.
|
||||||
|
String[] sizes = {
|
||||||
|
"4m", // usually this will success load the archived heap
|
||||||
|
"2m", // usually this will fail to loade th archived heap, but app can launch
|
||||||
|
"1m" // usually this will cause VM launch to fail with "Too small maximum heap"
|
||||||
|
};
|
||||||
|
for (String sz : sizes) {
|
||||||
|
String xmx = "-Xmx" + sz;
|
||||||
|
System.out.println("=======\n" + n + ". Exec with " + execGC + " " + xmx);
|
||||||
|
out = TestCommon.exec(helloJar,
|
||||||
|
execGC,
|
||||||
|
small1,
|
||||||
|
small2,
|
||||||
|
xmx,
|
||||||
|
"-Xlog:cds",
|
||||||
|
"Hello");
|
||||||
|
if (out.getExitValue() == 0) {
|
||||||
|
out.shouldContain(HELLO);
|
||||||
|
} else {
|
||||||
|
out.shouldContain("Too small maximum heap");
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,7 @@
|
||||||
* @bug 8214455
|
* @bug 8214455
|
||||||
* @requires vm.cds.write.archived.java.heap
|
* @requires vm.cds.write.archived.java.heap
|
||||||
* @requires (sun.arch.data.model == "64" & os.maxMemory > 4g)
|
* @requires (sun.arch.data.model == "64" & os.maxMemory > 4g)
|
||||||
|
* @requires vm.gc == "null"
|
||||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
|
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
|
||||||
* @build HeapFragmentationApp
|
* @build HeapFragmentationApp
|
||||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar HeapFragmentationApp.jar HeapFragmentationApp
|
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar HeapFragmentationApp.jar HeapFragmentationApp
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue