Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/hotspot/share/cds/metaspaceShared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1303,7 +1303,7 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
"Archive base address unaligned: " PTR_FORMAT ", needs alignment: %zu.",
p2i(base_address), base_address_alignment);

const size_t class_space_size = CompressedClassSpaceSize;
size_t class_space_size = CompressedClassSpaceSize;
assert(CompressedClassSpaceSize > 0 &&
is_aligned(CompressedClassSpaceSize, class_space_alignment),
"CompressedClassSpaceSize malformed: "
Expand All @@ -1312,6 +1312,16 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
const size_t ccs_begin_offset = align_up(archive_space_size, class_space_alignment);
const size_t gap_size = ccs_begin_offset - archive_space_size;

// Reduce class space size if it would not fit into the Klass encoding range
constexpr size_t max_encoding_range_size = 4 * G;
guarantee(archive_space_size < max_encoding_range_size - class_space_alignment, "Archive too large");
if ((archive_space_size + gap_size + class_space_size) > max_encoding_range_size) {
class_space_size = align_down(max_encoding_range_size - archive_space_size - gap_size, class_space_alignment);
log_info(metaspace)("CDS initialization: reducing class space size from " SIZE_FORMAT " to " SIZE_FORMAT,
CompressedClassSpaceSize, class_space_size);
FLAG_SET_ERGO(CompressedClassSpaceSize, class_space_size);
}

const size_t total_range_size =
archive_space_size + gap_size + class_space_size;

Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/runtime/globals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1396,7 +1396,7 @@ const int ObjectAlignmentInBytes = 8;
product(size_t, CompressedClassSpaceSize, 1*G, \
"Maximum size of class area in Metaspace when compressed " \
"class pointers are used") \
range(1*M, 3*G) \
range(1*M, LP64_ONLY(4*G) NOT_LP64(max_uintx)) \
\
develop(size_t, CompressedClassSpaceBaseAddress, 0, \
"Force the class space to be allocated at this address or " \
Expand Down
170 changes: 120 additions & 50 deletions test/hotspot/jtreg/runtime/CompressedOops/CompressedClassSpaceSize.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,75 +22,145 @@
*/

/*
* @test
* @test id=invalid
* @bug 8022865
* @summary Tests for the -XX:CompressedClassSpaceSize command line option
* @requires vm.bits == 64 & vm.opt.final.UseCompressedOops == true
* @requires vm.flagless
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
* @run driver CompressedClassSpaceSize
* @modules java.base/jdk.internal.misc java.management
* @run driver CompressedClassSpaceSize invalid
*/

/*
* @test id=valid_small
* @bug 8022865
* @summary Tests for the -XX:CompressedClassSpaceSize command line option
* @requires vm.bits == 64 & vm.opt.final.UseCompressedOops == true
* @requires vm.flagless
* @library /test/lib
* @modules java.base/jdk.internal.misc java.management
* @run driver CompressedClassSpaceSize valid_small
*/

/*
* @test id=valid_large_nocds
* @bug 8022865
* @summary Tests for the -XX:CompressedClassSpaceSize command line option
* @requires vm.bits == 64 & vm.opt.final.UseCompressedOops == true
* @requires vm.flagless
* @library /test/lib
* @modules java.base/jdk.internal.misc java.management
* @run driver CompressedClassSpaceSize valid_large_nocds
*/

/*
* @test id=valid_large_cds
* @bug 8022865
* @summary Tests for the -XX:CompressedClassSpaceSize command line option
* @requires vm.bits == 64 & vm.opt.final.UseCompressedOops == true & vm.cds
* @requires vm.flagless
* @library /test/lib
* @modules java.base/jdk.internal.misc java.management
* @run driver CompressedClassSpaceSize valid_large_cds
*/

import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;

public class CompressedClassSpaceSize {

public static void main(String[] args) throws Exception {
ProcessBuilder pb;
OutputAnalyzer output;
// Minimum size is 1MB
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:CompressedClassSpaceSize=0",
"-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("outside the allowed range")
.shouldHaveExitValue(1);

// Invalid size of -1 should be handled correctly
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:CompressedClassSpaceSize=-1",
"-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("Improperly specified VM option 'CompressedClassSpaceSize=-1'")
.shouldHaveExitValue(1);
final static long MB = 1024 * 1024;

final static long minAllowedClassSpaceSize = MB;
final static long minRealClassSpaceSize = 16 * MB;
final static long maxClassSpaceSize = 4096 * MB;

// Maximum size is 3GB
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:CompressedClassSpaceSize=4g",
"-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("outside the allowed range")
.shouldHaveExitValue(1);
// For the valid_large_cds sub test: we need to have a notion of what archive size to
// maximally expect, with a generous fudge factor to avoid having to tweak this test
// ofent. Note: today's default archives are around 16-20 MB.
final static long maxExpectedArchiveSize = 512 * MB;

public static void main(String[] args) throws Exception {
ProcessBuilder pb;
OutputAnalyzer output;

// Make sure the minimum size is set correctly and printed
// (Note: ccs size are rounded up to the next larger root chunk boundary (16m).
// Note that this is **reserved** size and does not affect rss.
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockDiagnosticVMOptions",
"-XX:CompressedClassSpaceSize=1m",
"-Xlog:gc+metaspace=trace",
"-version");
output = new OutputAnalyzer(pb.start());
output.shouldMatch("Compressed class space.*16777216")
.shouldHaveExitValue(0);
switch (args[0]) {
case "invalid": {
// < Minimum size
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:CompressedClassSpaceSize=0",
"-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("outside the allowed range")
.shouldHaveExitValue(1);

// Invalid size of -1 should be handled correctly
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:CompressedClassSpaceSize=-1",
"-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("Improperly specified VM option 'CompressedClassSpaceSize=-1'")
.shouldHaveExitValue(1);

// Make sure the maximum size is set correctly and printed
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockDiagnosticVMOptions",
"-XX:CompressedClassSpaceSize=3g",
"-Xlog:gc+metaspace=trace",
"-version");
output = new OutputAnalyzer(pb.start());
output.shouldMatch("Compressed class space.*3221225472")
.shouldHaveExitValue(0);
// > Maximum size
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:CompressedClassSpaceSize=" + maxClassSpaceSize + 1,
"-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("outside the allowed range")
.shouldHaveExitValue(1);

pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:-UseCompressedClassPointers",
"-XX:CompressedClassSpaceSize=" + minAllowedClassSpaceSize,
"-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("Setting CompressedClassSpaceSize has no effect when compressed class pointers are not used")
.shouldHaveExitValue(0);
}
break;
case "valid_small": {
// Make sure the minimum size is set correctly and printed
// (Note: ccs size are rounded up to the next larger root chunk boundary (16m).
// Note that this is **reserved** size and does not affect rss.
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockDiagnosticVMOptions",
"-XX:CompressedClassSpaceSize=" + minAllowedClassSpaceSize,
"-Xlog:gc+metaspace",
"-version");
output = new OutputAnalyzer(pb.start());
output.shouldMatch("Compressed class space.*" + minRealClassSpaceSize)
.shouldHaveExitValue(0);
}
break;
case "valid_large_nocds": {
// Without CDS, we should get 4G
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:CompressedClassSpaceSize=" + maxClassSpaceSize,
"-Xshare:off", "-Xlog:metaspace*", "-version");
output = new OutputAnalyzer(pb.start());
output.shouldMatch("Compressed class space.*" + maxClassSpaceSize)
.shouldHaveExitValue(0);
}
break;
case "valid_large_cds": {
// Create archive
pb = ProcessTools.createLimitedTestJavaProcessBuilder(
"-XX:SharedArchiveFile=./abc.jsa", "-Xshare:dump", "-version");
output = new OutputAnalyzer(pb.start());
output.shouldHaveExitValue(0);

pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:-UseCompressedClassPointers",
"-XX:CompressedClassSpaceSize=1m",
"-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("Setting CompressedClassSpaceSize has no effect when compressed class pointers are not used")
.shouldHaveExitValue(0);
// With CDS, class space should fill whatever the CDS archive leaves us (modulo alignment)
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:CompressedClassSpaceSize=" + maxClassSpaceSize,
"-XX:SharedArchiveFile=./abc.jsa", "-Xshare:on", "-Xlog:metaspace*", "-version");
output = new OutputAnalyzer(pb.start());
output.shouldHaveExitValue(0);
long reducedSize = Long.parseLong(
output.firstMatch("reducing class space size from " + maxClassSpaceSize + " to (\\d+)", 1));
if (reducedSize < (maxClassSpaceSize - maxExpectedArchiveSize)) {
output.reportDiagnosticSummary();
throw new RuntimeException("Class space size too small?");
}
output.shouldMatch("Compressed class space.*" + reducedSize);
}
break;
default:
throw new RuntimeException("invalid sub test " + args[0]);
}
}
}