8214455: Relocate CDS archived regions to the top of the G1 heap
Reviewed-by: tschatzl, ccheung
This commit is contained in:
parent
88eb2919f5
commit
78d1164ce2
src/hotspot/share/memory
test
hotspot/jtreg/runtime/cds/appcds
jdk/java/io/BufferedInputStream
@ -814,8 +814,8 @@ class RelocateBufferToRequested : public BitMapClosure {
|
||||
address top = _builder->buffer_top();
|
||||
address new_bottom = bottom + _buffer_to_requested_delta;
|
||||
address new_top = top + _buffer_to_requested_delta;
|
||||
log_debug(cds)("Relocating archive from [" INTPTR_FORMAT " - " INTPTR_FORMAT " ] to "
|
||||
"[" INTPTR_FORMAT " - " INTPTR_FORMAT " ]",
|
||||
log_debug(cds)("Relocating archive from [" INTPTR_FORMAT " - " INTPTR_FORMAT "] to "
|
||||
"[" INTPTR_FORMAT " - " INTPTR_FORMAT "]",
|
||||
p2i(bottom), p2i(top),
|
||||
p2i(new_bottom), p2i(new_top));
|
||||
}
|
||||
|
@ -215,6 +215,7 @@ void FileMapHeader::populate(FileMapInfo* mapinfo, size_t core_region_alignment)
|
||||
_narrow_oop_mode = CompressedOops::mode();
|
||||
_narrow_oop_base = CompressedOops::base();
|
||||
_narrow_oop_shift = CompressedOops::shift();
|
||||
_heap_begin = CompressedOops::begin();
|
||||
_heap_end = CompressedOops::end();
|
||||
}
|
||||
_compressed_oops = UseCompressedOops;
|
||||
@ -1811,6 +1812,8 @@ void FileMapInfo::map_heap_regions_impl() {
|
||||
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)(" heap range = [" PTR_FORMAT " - " PTR_FORMAT "]",
|
||||
p2i(header()->heap_begin()), p2i(header()->heap_end()));
|
||||
|
||||
log_info(cds)("The current max heap size = " SIZE_FORMAT "M, HeapRegion::GrainBytes = " SIZE_FORMAT,
|
||||
MaxHeapSize/M, HeapRegion::GrainBytes);
|
||||
@ -1818,6 +1821,8 @@ void FileMapInfo::map_heap_regions_impl() {
|
||||
p2i(CompressedKlassPointers::base()), CompressedKlassPointers::shift());
|
||||
log_info(cds)(" narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
|
||||
CompressedOops::mode(), p2i(CompressedOops::base()), CompressedOops::shift());
|
||||
log_info(cds)(" heap range = [" PTR_FORMAT " - " PTR_FORMAT "]",
|
||||
p2i(CompressedOops::begin()), p2i(CompressedOops::end()));
|
||||
|
||||
if (narrow_klass_base() != CompressedKlassPointers::base() ||
|
||||
narrow_klass_shift() != CompressedKlassPointers::shift()) {
|
||||
@ -1828,15 +1833,18 @@ void FileMapInfo::map_heap_regions_impl() {
|
||||
if (narrow_oop_mode() != CompressedOops::mode() ||
|
||||
narrow_oop_base() != CompressedOops::base() ||
|
||||
narrow_oop_shift() != CompressedOops::shift()) {
|
||||
log_info(cds)("CDS heap data need to be relocated because the archive was created with an incompatible oop encoding mode.");
|
||||
log_info(cds)("CDS heap data needs to be relocated because the archive was created with an incompatible oop encoding mode.");
|
||||
_heap_pointers_need_patching = true;
|
||||
} else {
|
||||
MemRegion range = get_heap_regions_range_with_current_oop_encoding_mode();
|
||||
if (!CompressedOops::is_in(range)) {
|
||||
log_info(cds)("CDS heap data need to be relocated because");
|
||||
log_info(cds)("CDS heap data needs 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(CompressedOops::begin()), p2i(CompressedOops::end()));
|
||||
_heap_pointers_need_patching = true;
|
||||
} else if (header()->heap_end() != CompressedOops::end()) {
|
||||
log_info(cds)("CDS heap data needs to be relocated to the end of the runtime heap to reduce fragmentation");
|
||||
_heap_pointers_need_patching = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1852,7 +1860,7 @@ void FileMapInfo::map_heap_regions_impl() {
|
||||
// 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 = header()->heap_end();
|
||||
address runtime_heap_end = (address)CompressedOops::end();
|
||||
address runtime_heap_end = CompressedOops::end();
|
||||
delta = runtime_heap_end - dumptime_heap_end;
|
||||
}
|
||||
|
||||
@ -1868,7 +1876,7 @@ void FileMapInfo::map_heap_regions_impl() {
|
||||
// open regions.
|
||||
size_t align = size_t(relocated_closed_heap_region_bottom) % HeapRegion::GrainBytes;
|
||||
delta -= align;
|
||||
log_info(cds)("CDS heap data need to be relocated lower by a further " SIZE_FORMAT
|
||||
log_info(cds)("CDS heap data needs to be relocated lower by a further " SIZE_FORMAT
|
||||
" bytes to " INTX_FORMAT " to be aligned with HeapRegion::GrainBytes",
|
||||
align, delta);
|
||||
HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift());
|
||||
@ -1996,6 +2004,7 @@ void FileMapInfo::patch_archived_heap_embedded_pointers() {
|
||||
return;
|
||||
}
|
||||
|
||||
log_info(cds)("patching heap embedded pointers");
|
||||
patch_archived_heap_embedded_pointers(closed_archive_heap_ranges,
|
||||
num_closed_archive_heap_ranges,
|
||||
MetaspaceShared::first_closed_archive_heap_region);
|
||||
|
@ -199,6 +199,7 @@ class FileMapHeader: private CDSFileMapHeaderBase {
|
||||
bool _compressed_class_ptrs; // save the flag UseCompressedClassPointers
|
||||
size_t _cloned_vtables_offset; // The address of the first cloned vtable
|
||||
size_t _serialized_data_offset; // Data accessed using {ReadClosure,WriteClosure}::serialize()
|
||||
address _heap_begin; // heap begin at dump time.
|
||||
address _heap_end; // heap end at dump time.
|
||||
bool _base_archive_is_default; // indicates if the base archive is the system default one
|
||||
|
||||
@ -262,6 +263,7 @@ public:
|
||||
address narrow_klass_base() const { return (address)mapped_base_address(); }
|
||||
char* cloned_vtables() const { return from_mapped_offset(_cloned_vtables_offset); }
|
||||
char* serialized_data() const { return from_mapped_offset(_serialized_data_offset); }
|
||||
address heap_begin() const { return _heap_begin; }
|
||||
address heap_end() const { return _heap_end; }
|
||||
bool base_archive_is_default() const { return _base_archive_is_default; }
|
||||
const char* jvm_ident() const { return _jvm_ident; }
|
||||
|
@ -346,6 +346,8 @@ void HeapShared::archive_java_heap_objects(GrowableArray<MemRegion>* closed,
|
||||
// Cache for recording where the archived objects are copied to
|
||||
create_archived_object_cache();
|
||||
|
||||
log_info(cds)("Heap range = [" PTR_FORMAT " - " PTR_FORMAT "]",
|
||||
p2i(CompressedOops::begin()), p2i(CompressedOops::end()));
|
||||
log_info(cds)("Dumping objects to closed archive heap region ...");
|
||||
copy_closed_archive_heap_objects(closed);
|
||||
|
||||
|
@ -452,6 +452,12 @@ public class TestCommon extends CDSTestUtils {
|
||||
return new Result(opts, runWithArchive(opts));
|
||||
}
|
||||
|
||||
public static Result runWithoutCDS(String... suffix) throws Exception {
|
||||
AppCDSOptions opts = (new AppCDSOptions());
|
||||
opts.addSuffix(suffix).setXShareMode("off");;
|
||||
return new Result(opts, runWithArchive(opts));
|
||||
}
|
||||
|
||||
public static Result runWithRelativePath(String jarDir, String... suffix) throws Exception {
|
||||
AppCDSOptions opts = (new AppCDSOptions());
|
||||
opts.setAppJarDir(jarDir);
|
||||
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
public class HeapFragmentationApp {
|
||||
public static void main(String args[]) throws Exception {
|
||||
int BUF_SIZE = Integer.parseInt(args[0]);
|
||||
System.out.println("allocating byte[" + BUF_SIZE + "]");
|
||||
byte[] array = new byte[BUF_SIZE];
|
||||
System.out.println("array = " + array);
|
||||
System.out.println("array.length = " + array.length);
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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
|
||||
* @summary Relocate CDS archived regions to the top of the G1 heap
|
||||
* @bug 8214455
|
||||
* @requires vm.cds.archived.java.heap
|
||||
* @requires (sun.arch.data.model == "64" & os.maxMemory > 4g)
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
|
||||
* @build HeapFragmentationApp
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar HeapFragmentationApp.jar HeapFragmentationApp
|
||||
* @run driver HeapFragmentationTest
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.helpers.ClassFileInstaller;
|
||||
|
||||
public class HeapFragmentationTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String mainClass = "HeapFragmentationApp";
|
||||
String appJar = ClassFileInstaller.getJarPath(mainClass + ".jar");
|
||||
String appClasses[] = TestCommon.list(mainClass);
|
||||
|
||||
// We run with a 1400m heap, so we should be able to allocate a 1000m buffer, regardless
|
||||
// of the heap size chosen at dump time.
|
||||
String dumpTimeHeapSize = "-Xmx800m";
|
||||
String runTimeHeapSize = "-Xmx1400m";
|
||||
String BUFF_SIZE = Integer.toString(1000 * 1024 * 1024);
|
||||
String successOutput = "array.length = " + BUFF_SIZE;
|
||||
|
||||
// On Linux/x64, this would (usually, if not affected by ASLR) force the low end of
|
||||
// the heap to be at 0x600000000. Thus, the heap ranges would be
|
||||
//
|
||||
// dump time: [0x600000000 ... 0x600000000 + 800m]
|
||||
// [AHR] <- archived heap regions are dumped at here
|
||||
//
|
||||
// run time: [0x600000000 ............... 0x600000000 + 1400m]
|
||||
// [AHR] <- archived heap regions are moved to here
|
||||
// |<---- max allocatable size ----->|
|
||||
String heapBase = "-XX:HeapBaseMinAddress=0x600000000";
|
||||
|
||||
TestCommon.dump(appJar, appClasses,
|
||||
heapBase,
|
||||
dumpTimeHeapSize, "-Xlog:cds=debug");
|
||||
|
||||
String execArgs[] = TestCommon.concat("-cp", appJar,
|
||||
"-showversion",
|
||||
heapBase,
|
||||
"-Xlog:cds=debug",
|
||||
"-Xlog:gc+heap+exit",
|
||||
"-Xlog:gc,gc+heap,gc+ergo+heap",
|
||||
"-XX:+CrashOnOutOfMemoryError",
|
||||
"-XX:+IgnoreUnrecognizedVMOptions",
|
||||
"-XX:+G1ExitOnExpansionFailure");
|
||||
|
||||
// First, make sure the test runs without CDS
|
||||
TestCommon.runWithoutCDS(TestCommon.concat(execArgs, runTimeHeapSize, mainClass, BUFF_SIZE))
|
||||
.assertNormalExit(successOutput);
|
||||
|
||||
// Run with CDS. The archived heap regions should be relocated to avoid fragmentation.
|
||||
TestCommon.run(TestCommon.concat(execArgs, runTimeHeapSize, mainClass, BUFF_SIZE))
|
||||
.assertNormalExit(successOutput);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -23,11 +23,12 @@
|
||||
|
||||
/* @test
|
||||
* @bug 7129312
|
||||
* @requires (sun.arch.data.model == "64" & os.maxMemory > 4g)
|
||||
* @requires (sun.arch.data.model == "64" & os.maxMemory > 4g)
|
||||
* @summary BufferedInputStream calculates negative array size with large
|
||||
* streams and mark
|
||||
* @run main/othervm -Xmx4G -Xlog:gc,gc+heap,gc+ergo+heap -XX:+CrashOnOutOfMemoryError
|
||||
-XX:+IgnoreUnrecognizedVMOptions -XX:+G1ExitOnExpansionFailure
|
||||
-Xlog:cds=debug
|
||||
LargeCopyWithMark
|
||||
*/
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user