--- old/src/share/vm/memory/filemap.cpp 2016-06-14 20:06:01.134598527 -0400 +++ new/src/share/vm/memory/filemap.cpp 2016-06-14 20:05:59.570510031 -0400 @@ -651,6 +651,20 @@ return base; } +bool FileMapInfo::verify_compressed_class_encoding() { + assert(UseSharedSpaces, "sanity"); // should only be called at CDS runtime + if (UseCompressedClassPointers) { + // Check that all the narrow oop and klass encodings match the archive + if (narrow_klass_base() != Universe::narrow_klass_base() || + narrow_klass_shift() != Universe::narrow_klass_shift()) { + fail_continue( + "Unable to use shared archive. The current CompressedClassPointers encoding differs from that archived"); + return false; + } + } + return true; +} + static MemRegion *string_ranges = NULL; static int num_ranges = 0; bool FileMapInfo::map_string_regions() { @@ -658,9 +672,7 @@ if (UseG1GC && UseCompressedOops && UseCompressedClassPointers) { // 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()) { + narrow_oop_shift() != Universe::narrow_oop_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 " --- old/src/share/vm/memory/filemap.hpp 2016-06-14 20:06:05.850865374 -0400 +++ new/src/share/vm/memory/filemap.hpp 2016-06-14 20:06:04.294777330 -0400 @@ -235,6 +235,7 @@ void unmap_region(int i); void dealloc_string_regions(); bool verify_region_checksum(int i); + bool verify_compressed_class_encoding(); void close(); bool is_open() { return _file_open; } ReservedSpace reserve_shared_memory(); --- old/src/share/vm/memory/metaspace.cpp 2016-06-14 20:06:10.551131314 -0400 +++ new/src/share/vm/memory/metaspace.cpp 2016-06-14 20:06:09.003043724 -0400 @@ -2880,7 +2880,11 @@ address lower_base; address higher_address; #if INCLUDE_CDS - if (UseSharedSpaces) { + if (DumpSharedSpaces) { + assert(cds_base < metaspace_base, "Sanity check"); + higher_address = (address)(metaspace_base + compressed_class_space_size()); + lower_base = cds_base; + } else if (UseSharedSpaces) { higher_address = MAX2((address)(cds_base + FileMapInfo::shared_spaces_size()), (address)(metaspace_base + compressed_class_space_size())); lower_base = MIN2(metaspace_base, cds_base); @@ -2902,24 +2906,10 @@ if ((uint64_t)(higher_address - lower_base) <= UnscaledClassSpaceMax) { Universe::set_narrow_klass_shift(0); } else { - assert(!UseSharedSpaces, "Cannot shift with UseSharedSpaces"); Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes); } } -#if INCLUDE_CDS -// Return TRUE if the specified metaspace_base and cds_base are close enough -// to work with compressed klass pointers. -bool Metaspace::can_use_cds_with_metaspace_addr(char* metaspace_base, address cds_base) { - assert(cds_base != 0 && UseSharedSpaces, "Only use with CDS"); - assert(UseCompressedClassPointers, "Only use with CompressedKlassPtrs"); - address lower_base = MIN2((address)metaspace_base, cds_base); - address higher_address = MAX2((address)(cds_base + FileMapInfo::shared_spaces_size()), - (address)(metaspace_base + compressed_class_space_size())); - return ((uint64_t)(higher_address - lower_base) <= UnscaledClassSpaceMax); -} -#endif - // Try to allocate the metaspace at the requested addr. void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base) { assert(using_class_space(), "called improperly"); @@ -2958,19 +2948,6 @@ a < (char*)(1024*G); a += 4*G) { -#if INCLUDE_CDS - if (UseSharedSpaces - && ! can_use_cds_with_metaspace_addr(a, cds_base)) { - // We failed to find an aligned base that will reach. Fall - // back to using our requested addr. - metaspace_rs = ReservedSpace(compressed_class_space_size(), - _reserve_alignment, - large_pages, - requested_addr); - break; - } -#endif - metaspace_rs = ReservedSpace(compressed_class_space_size(), _reserve_alignment, large_pages, @@ -2988,11 +2965,9 @@ size_t increment = align_size_up(1*G, _reserve_alignment); // Keep trying to allocate the metaspace, increasing the requested_addr - // by 1GB each time, until we reach an address that will no longer allow - // use of CDS with compressed klass pointers. + // by 1GB each time char *addr = requested_addr; - while (!metaspace_rs.is_reserved() && (addr + increment > addr) && - can_use_cds_with_metaspace_addr(addr + increment, cds_base)) { + while (!metaspace_rs.is_reserved() && (addr + increment > addr)) { addr = addr + increment; metaspace_rs = ReservedSpace(compressed_class_space_size(), _reserve_alignment, large_pages, addr); @@ -3017,13 +2992,6 @@ // If we got here then the metaspace got allocated. MemTracker::record_virtual_memory_type((address)metaspace_rs.base(), mtClass); -#if INCLUDE_CDS - // Verify that we can use shared spaces. Otherwise, turn off CDS. - if (UseSharedSpaces && !can_use_cds_with_metaspace_addr(metaspace_rs.base(), cds_base)) { - FileMapInfo::stop_sharing_and_unmap( - "Could not allocate metaspace at a compatible address"); - } -#endif set_narrow_klass_base_and_shift((address)metaspace_rs.base(), UseSharedSpaces ? (address)cds_base : 0); @@ -3141,23 +3109,13 @@ } #ifdef _LP64 - if (cds_total + compressed_class_space_size() > UnscaledClassSpaceMax) { - vm_exit_during_initialization("Unable to dump shared archive.", - err_msg("Size of archive (" SIZE_FORMAT ") + compressed class space (" - SIZE_FORMAT ") == total (" SIZE_FORMAT ") is larger than compressed " - "klass limit: " UINT64_FORMAT, cds_total, compressed_class_space_size(), - cds_total + compressed_class_space_size(), UnscaledClassSpaceMax)); - } - // Set the compressed klass pointer base so that decoding of these pointers works // properly when creating the shared archive. assert(UseCompressedOops && UseCompressedClassPointers, "UseCompressedOops and UseCompressedClassPointers must be set"); - Universe::set_narrow_klass_base((address)_space_list->current_virtual_space()->bottom()); - log_develop_trace(gc, metaspace)("Setting_narrow_klass_base to Address: " PTR_FORMAT, - p2i(_space_list->current_virtual_space()->bottom())); - - Universe::set_narrow_klass_shift(0); + address cds_base = (address)_space_list->current_virtual_space()->bottom(); + address metaspace_base = (address)(cds_base + cds_total); + set_narrow_klass_base_and_shift(metaspace_base, cds_base); #endif // _LP64 #endif // INCLUDE_CDS } else { @@ -3183,9 +3141,12 @@ // 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(); + // Verify if compressed class pointer encoding is the same as the archived + if (mapinfo->verify_compressed_class_encoding()) { + // 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 { --- /dev/null 2016-04-23 09:44:14.802912998 -0400 +++ new/test/runtime/SharedArchiveFile/LargeSpaces.java 2016-06-14 20:06:13.923322113 -0400 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015, 2016, 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 CDS dumping with large combined CDS spaces and compressed class space + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires (vm.opt.UseCompressedClassPointers == null) | (vm.opt.UseCompressedClassPointers == true) + * @requires (vm.gc=="G1" | vm.gc=="null") + * @library /testlibrary /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @build jdk.test.lib.* + * @run main LargeSpaces + */ +import jdk.test.lib.*; + +public class LargeSpaces { + public static void main(String[] args) throws Exception { + boolean test_runtime = true; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=./largeSharedSpaces.jsa", + "-XX:SharedMiscDataSize=800M", + "-XX:SharedMiscCodeSize=1G", + "-XX:CompressedClassSpaceSize=3G", + "-Xshare:dump"); + OutputAnalyzer dumpOutput = new OutputAnalyzer(pb.start()); + try { + dumpOutput.shouldContain("Loading classes to share"); + dumpOutput.shouldNotContain("larger than compressed klass limit: 4294967296"); + dumpOutput.shouldHaveExitValue(0); + } catch (RuntimeException e) { + if (dumpOutput.getOutput().indexOf("Cannot dump shared archive") != -1) { + test_runtime = false; + } else { + throw new RuntimeException("Unexpected failure"); + } + } + + if (test_runtime) { + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=./largeSharedSpaces.jsa", + "-Xshare:on", + "-XX:CompressedClassSpaceSize=3G", + "-version"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + try { + output.shouldContain("sharing"); + output.shouldHaveExitValue(0); + } catch (RuntimeException e) { + output.shouldContain("Unable to use shared archive"); + output.shouldHaveExitValue(1); + } + } + } +}