8098821: Crash in system dictionary initialization with shared strings
Summary: map string regions after the compressed class base is known
Reviewed-by: iklam, dcubed
Contributed-by: coleen.phillimore@oracle.com, mikhailo.seledtsov@oracle.com
--- a/hotspot/src/share/vm/memory/filemap.cpp Tue Jun 16 11:58:25 2015 +0200
+++ b/hotspot/src/share/vm/memory/filemap.cpp Wed Jun 17 21:44:48 2015 +0000
@@ -172,6 +172,8 @@
_narrow_oop_mode = Universe::narrow_oop_mode();
_narrow_oop_shift = Universe::narrow_oop_shift();
_max_heap_size = MaxHeapSize;
+ _narrow_klass_base = Universe::narrow_klass_base();
+ _narrow_klass_shift = Universe::narrow_klass_shift();
_classpath_entry_table_size = mapinfo->_classpath_entry_table_size;
_classpath_entry_table = mapinfo->_classpath_entry_table;
_classpath_entry_size = mapinfo->_classpath_entry_size;
@@ -652,8 +654,18 @@
bool FileMapInfo::map_string_regions() {
#if INCLUDE_ALL_GCS
if (UseG1GC && UseCompressedOops && UseCompressedClassPointers) {
- if (narrow_oop_mode() == Universe::narrow_oop_mode() &&
- narrow_oop_shift() == Universe::narrow_oop_shift()) {
+ // Check that all the narrow oop and klass encodings match the archive
+ if (narrow_oop_mode() != Universe::narrow_oop_mode() ||
+ narrow_oop_shift() != Universe::narrow_oop_shift() ||
+ narrow_klass_base() != Universe::narrow_klass_base() ||
+ narrow_klass_shift() != Universe::narrow_klass_shift()) {
+ if (PrintSharedSpaces && _header->_space[MetaspaceShared::first_string]._used > 0) {
+ tty->print_cr("Shared string 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 %dM.", max_heap_size()/M);
+ }
+ } else {
string_ranges = new MemRegion[MetaspaceShared::max_strings];
struct FileMapInfo::FileMapHeader::space_info* si;
@@ -671,6 +683,7 @@
}
if (num_ranges == 0) {
+ StringTable::ignore_shared_strings(true);
return true; // no shared string data
}
@@ -702,15 +715,14 @@
return false;
}
}
- return true; // the shared string data is mapped successfuly
- } else {
- // narrow oop encoding differ, the shared string data are not used
- if (PrintSharedSpaces && _header->_space[MetaspaceShared::first_string]._used > 0) {
- tty->print_cr("Shared string data from the CDS archive is being ignored. "
- "The current CompressedOops encoding differs from that archived "
- "due to heap size change. The archive was dumped using max heap "
- "size %dM.", max_heap_size() >> 20);
+
+ if (!verify_string_regions()) {
+ fail_continue("Shared string regions are corrupt");
+ return false;
}
+
+ // the shared string data is mapped successfully
+ return true;
}
} else {
if (PrintSharedSpaces && _header->_space[MetaspaceShared::first_string]._used > 0) {
--- a/hotspot/src/share/vm/memory/filemap.hpp Tue Jun 16 11:58:25 2015 +0200
+++ b/hotspot/src/share/vm/memory/filemap.hpp Wed Jun 17 21:44:48 2015 +0000
@@ -97,6 +97,8 @@
int _narrow_oop_shift; // compressed oop encoding shift
uintx _max_heap_size; // java max heap size during dumping
Universe::NARROW_OOP_MODE _narrow_oop_mode; // compressed oop encoding mode
+ int _narrow_klass_shift; // save narrow klass base and shift
+ address _narrow_klass_base;
struct space_info {
int _crc; // crc checksum of the current space
@@ -178,6 +180,8 @@
Universe::NARROW_OOP_MODE narrow_oop_mode() { return _header->_narrow_oop_mode; }
int narrow_oop_shift() { return _header->_narrow_oop_shift; }
uintx max_heap_size() { return _header->_max_heap_size; }
+ address narrow_klass_base() const { return _header->_narrow_klass_base; }
+ int narrow_klass_shift() const { return _header->_narrow_klass_shift; }
size_t space_capacity(int i) { return _header->_space[i]._capacity; }
struct FileMapHeader* header() { return _header; }
--- a/hotspot/src/share/vm/memory/metaspace.cpp Tue Jun 16 11:58:25 2015 +0200
+++ b/hotspot/src/share/vm/memory/metaspace.cpp Wed Jun 17 21:44:48 2015 +0000
@@ -3293,12 +3293,12 @@
#endif // _LP64
#endif // INCLUDE_CDS
} else {
-#if INCLUDE_CDS
// If using shared space, open the file that contains the shared space
// and map in the memory before initializing the rest of metaspace (so
// the addresses don't conflict)
address cds_address = NULL;
if (UseSharedSpaces) {
+#if INCLUDE_CDS
FileMapInfo* mapinfo = new FileMapInfo();
// Open the shared archive file, read and validate the header. If
@@ -3308,26 +3308,29 @@
if (mapinfo->initialize() && MetaspaceShared::map_shared_spaces(mapinfo)) {
cds_total = FileMapInfo::shared_spaces_size();
cds_address = (address)mapinfo->header()->region_addr(0);
+#ifdef _LP64
+ if (using_class_space()) {
+ char* cds_end = (char*)(cds_address + cds_total);
+ cds_end = (char *)align_ptr_up(cds_end, _reserve_alignment);
+ // If UseCompressedClassPointers is set then allocate the metaspace area
+ // above the heap and above the CDS area (if it exists).
+ allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address);
+ // Map the shared string space after compressed pointers
+ // because it relies on compressed class pointers setting to work
+ mapinfo->map_string_regions();
+ }
+#endif // _LP64
} else {
assert(!mapinfo->is_open() && !UseSharedSpaces,
"archive file not closed or shared spaces not disabled.");
}
+#endif // INCLUDE_CDS
}
-#endif // INCLUDE_CDS
+
#ifdef _LP64
- // If UseCompressedClassPointers is set then allocate the metaspace area
- // above the heap and above the CDS area (if it exists).
- if (using_class_space()) {
- if (UseSharedSpaces) {
-#if INCLUDE_CDS
- char* cds_end = (char*)(cds_address + cds_total);
- cds_end = (char *)align_ptr_up(cds_end, _reserve_alignment);
- allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address);
-#endif
- } else {
- char* base = (char*)align_ptr_up(Universe::heap()->reserved_region().end(), _reserve_alignment);
- allocate_metaspace_compressed_klass_ptrs(base, 0);
- }
+ if (!UseSharedSpaces && using_class_space()) {
+ char* base = (char*)align_ptr_up(Universe::heap()->reserved_region().end(), _reserve_alignment);
+ allocate_metaspace_compressed_klass_ptrs(base, 0);
}
#endif // _LP64
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp Tue Jun 16 11:58:25 2015 +0200
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp Wed Jun 17 21:44:48 2015 +0000
@@ -1001,8 +1001,6 @@
mapinfo->verify_region_checksum(md) &&
(_mc_base = mapinfo->map_region(mc)) != NULL &&
mapinfo->verify_region_checksum(mc) &&
- mapinfo->map_string_regions() &&
- mapinfo->verify_string_regions() &&
(image_alignment == (size_t)max_alignment()) &&
mapinfo->validate_classpath_entry_table()) {
// Success (no need to do anything)
@@ -1014,7 +1012,6 @@
if (_rw_base != NULL) mapinfo->unmap_region(rw);
if (_md_base != NULL) mapinfo->unmap_region(md);
if (_mc_base != NULL) mapinfo->unmap_region(mc);
- mapinfo->unmap_string_regions();
#ifndef _WINDOWS
// Release the entire mapped region
shared_rs.release();
--- a/hotspot/src/share/vm/prims/whitebox.cpp Tue Jun 16 11:58:25 2015 +0200
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Wed Jun 17 21:44:48 2015 +0000
@@ -1213,6 +1213,10 @@
return MetaspaceShared::is_in_shared_space((void*)obj_oop);
WB_END
+WB_ENTRY(jboolean, WB_AreSharedStringsIgnored(JNIEnv* env))
+ return StringTable::shared_string_ignored();
+WB_END
+
//Some convenience methods to deal with objects from java
int WhiteBox::offset_for_field(const char* field_name, oop object,
Symbol* signature_symbol) {
@@ -1438,6 +1442,7 @@
CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;",
(void*)&WB_GetMethodStringOption},
{CC"isShared", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
+ {CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored },
};
#undef CC