8138983: Runtime: implement ranges for Shared*** flags

Implement ranges.

Reviewed-by: ddmitriev, dholmes, jiangli
This commit is contained in:
Gerard Ziemski 2015-11-19 16:32:41 -06:00
parent dcd4a03963
commit 97470c5146
11 changed files with 274 additions and 146 deletions

View File

@ -137,7 +137,7 @@ juint* CompactHashtableWriter::dump_buckets(juint* compact_table, juint* p,
if (_type == CompactHashtable<Symbol*, char>::_symbol_table) {
base_address = uintx(MetaspaceShared::shared_rs()->base());
max_delta = uintx(MetaspaceShared::shared_rs()->size());
assert(max_delta <= 0x7fffffff, "range check");
assert(max_delta <= MAX_SHARED_DELTA, "range check");
} else {
assert((_type == CompactHashtable<oop, char>::_string_table), "unknown table");
assert(UseCompressedOops, "UseCompressedOops is required");

View File

@ -3230,36 +3230,6 @@ void Metaspace::global_initialize() {
SharedMiscDataSize = align_size_up(SharedMiscDataSize, max_alignment);
SharedMiscCodeSize = align_size_up(SharedMiscCodeSize, max_alignment);
// make sure SharedReadOnlySize and SharedReadWriteSize are not less than
// the minimum values.
if (SharedReadOnlySize < MetaspaceShared::min_ro_size){
report_out_of_shared_space(SharedReadOnly);
}
if (SharedReadWriteSize < MetaspaceShared::min_rw_size){
report_out_of_shared_space(SharedReadWrite);
}
// the min_misc_data_size and min_misc_code_size estimates are based on
// MetaspaceShared::generate_vtable_methods().
// The minimum size only accounts for the vtable methods. Any size less than the
// minimum required size would cause vm crash when allocating the vtable methods.
uint min_misc_data_size = align_size_up(
MetaspaceShared::num_virtuals * MetaspaceShared::vtbl_list_size * sizeof(void*), max_alignment);
if (SharedMiscDataSize < min_misc_data_size) {
report_out_of_shared_space(SharedMiscData);
}
uintx min_misc_code_size = align_size_up(
(MetaspaceShared::num_virtuals * MetaspaceShared::vtbl_list_size) *
(sizeof(void*) + MetaspaceShared::vtbl_method_size) + MetaspaceShared::vtbl_common_code_size,
max_alignment);
if (SharedMiscCodeSize < min_misc_code_size) {
report_out_of_shared_space(SharedMiscCode);
}
// Initialize with the sum of the shared space sizes. The read-only
// and read write metaspace chunks will be allocated out of this and the
// remainder is the misc code and data chunks.

View File

@ -32,14 +32,55 @@
#include "utilities/exceptions.hpp"
#include "utilities/macros.hpp"
#define LargeSharedArchiveSize (300*M)
#define HugeSharedArchiveSize (800*M)
#define ReadOnlyRegionPercentage 0.4
#define ReadWriteRegionPercentage 0.55
#define MiscDataRegionPercentage 0.03
#define MiscCodeRegionPercentage 0.02
#define LargeThresholdClassCount 5000
#define HugeThresholdClassCount 40000
#define DEFAULT_VTBL_LIST_SIZE (17) // number of entries in the shared space vtable list.
#define DEFAULT_VTBL_VIRTUALS_COUNT (200) // maximum number of virtual functions
// If virtual functions are added to Metadata,
// this number needs to be increased. Also,
// SharedMiscCodeSize will need to be increased.
// The following 2 sizes were based on
// MetaspaceShared::generate_vtable_methods()
#define DEFAULT_VTBL_METHOD_SIZE (16) // conservative size of the mov1 and jmp instructions
// for the x64 platform
#define DEFAULT_VTBL_COMMON_CODE_SIZE (1*K) // conservative size of the "common_code" for the x64 platform
#define DEFAULT_SHARED_READ_WRITE_SIZE (NOT_LP64(12*M) LP64_ONLY(16*M))
#define MIN_SHARED_READ_WRITE_SIZE (NOT_LP64(7*M) LP64_ONLY(12*M))
#define DEFAULT_SHARED_READ_ONLY_SIZE (NOT_LP64(12*M) LP64_ONLY(16*M))
#define MIN_SHARED_READ_ONLY_SIZE (NOT_LP64(8*M) LP64_ONLY(9*M))
// the MIN_SHARED_MISC_DATA_SIZE and MIN_SHARED_MISC_CODE_SIZE estimates are based on
// MetaspaceShared::generate_vtable_methods().
// The minimum size only accounts for the vtable methods. Any size less than the
// minimum required size would cause vm crash when allocating the vtable methods.
#define SHARED_MISC_SIZE_FOR(size) (DEFAULT_VTBL_VIRTUALS_COUNT*DEFAULT_VTBL_LIST_SIZE*size)
#define DEFAULT_SHARED_MISC_DATA_SIZE (NOT_LP64(2*M) LP64_ONLY(4*M))
#define MIN_SHARED_MISC_DATA_SIZE (SHARED_MISC_SIZE_FOR(sizeof(void*)))
#define DEFAULT_SHARED_MISC_CODE_SIZE (120*K)
#define MIN_SHARED_MISC_CODE_SIZE (SHARED_MISC_SIZE_FOR(sizeof(void*))+SHARED_MISC_SIZE_FOR(DEFAULT_VTBL_METHOD_SIZE)+DEFAULT_VTBL_COMMON_CODE_SIZE)
#define DEFAULT_COMBINED_SIZE (DEFAULT_SHARED_READ_WRITE_SIZE+DEFAULT_SHARED_READ_ONLY_SIZE+DEFAULT_SHARED_MISC_DATA_SIZE+DEFAULT_SHARED_MISC_CODE_SIZE)
// the max size is the MAX size (ie. 0x7FFFFFFF) - the total size of
// the other 3 sections - page size (to avoid overflow in case the final
// size will get aligned up on page size)
#define SHARED_PAGE ((size_t)os::vm_page_size())
#define MAX_SHARED_DELTA (0x7FFFFFFF)
#define MAX_SHARED_READ_WRITE_SIZE (MAX_SHARED_DELTA-(MIN_SHARED_READ_ONLY_SIZE+MIN_SHARED_MISC_DATA_SIZE+MIN_SHARED_MISC_CODE_SIZE)-SHARED_PAGE)
#define MAX_SHARED_READ_ONLY_SIZE (MAX_SHARED_DELTA-(MIN_SHARED_READ_WRITE_SIZE+MIN_SHARED_MISC_DATA_SIZE+MIN_SHARED_MISC_CODE_SIZE)-SHARED_PAGE)
#define MAX_SHARED_MISC_DATA_SIZE (MAX_SHARED_DELTA-(MIN_SHARED_READ_WRITE_SIZE+MIN_SHARED_READ_ONLY_SIZE+MIN_SHARED_MISC_CODE_SIZE)-SHARED_PAGE)
#define MAX_SHARED_MISC_CODE_SIZE (MAX_SHARED_DELTA-(MIN_SHARED_READ_WRITE_SIZE+MIN_SHARED_READ_ONLY_SIZE+MIN_SHARED_MISC_DATA_SIZE)-SHARED_PAGE)
#define LargeSharedArchiveSize (300*M)
#define HugeSharedArchiveSize (800*M)
#define ReadOnlyRegionPercentage 0.4
#define ReadWriteRegionPercentage 0.55
#define MiscDataRegionPercentage 0.03
#define MiscCodeRegionPercentage 0.02
#define LargeThresholdClassCount 5000
#define HugeThresholdClassCount 40000
#define SET_ESTIMATED_SIZE(type, region) \
Shared ##region## Size = FLAG_IS_DEFAULT(Shared ##region## Size) ? \
@ -69,21 +110,10 @@ class MetaspaceShared : AllStatic {
static bool _archive_loading_failed;
public:
enum {
vtbl_list_size = 17, // number of entries in the shared space vtable list.
num_virtuals = 200, // maximum number of virtual functions
// If virtual functions are added to Metadata,
// this number needs to be increased. Also,
// SharedMiscCodeSize will need to be increased.
// The following 2 sizes were based on
// MetaspaceShared::generate_vtable_methods()
vtbl_method_size = 16, // conservative size of the mov1 and jmp instructions
// for the x64 platform
vtbl_common_code_size = (1*K) // conservative size of the "common_code" for the x64 platform
};
enum {
min_ro_size = NOT_LP64(8*M) LP64_ONLY(9*M), // minimum ro and rw regions sizes based on dumping
min_rw_size = NOT_LP64(7*M) LP64_ONLY(12*M) // of a shared archive using the default classlist
vtbl_list_size = DEFAULT_VTBL_LIST_SIZE,
num_virtuals = DEFAULT_VTBL_VIRTUALS_COUNT,
vtbl_method_size = DEFAULT_VTBL_METHOD_SIZE,
vtbl_common_code_size = DEFAULT_VTBL_COMMON_CODE_SIZE
};
enum {

View File

@ -223,7 +223,7 @@ void emit_constraint_double(const char* name, CommandLineFlagConstraintFunc_doub
#define EMIT_CONSTRAINT_CHECK(func, type) , func, CommandLineFlagConstraint::type
// the "name" argument must be a string literal
#define INITIAL_CONSTRAINTS_SIZE 45
#define INITIAL_CONSTRAINTS_SIZE 69
GrowableArray<CommandLineFlagConstraint*>* CommandLineFlagConstraintList::_constraints = NULL;
CommandLineFlagConstraint::ConstraintType CommandLineFlagConstraintList::_validating_type = CommandLineFlagConstraint::AtParse;

View File

@ -279,7 +279,7 @@ void emit_range_double(const char* name, double min, double max) {
// Generate func argument to pass into emit_range_xxx functions
#define EMIT_RANGE_CHECK(a, b) , a, b
#define INITIAL_RANGES_SIZE 205
#define INITIAL_RANGES_SIZE 320
GrowableArray<CommandLineFlagRange*>* CommandLineFlagRangeList::_ranges = NULL;
// Check the ranges of all flags that have them

View File

@ -25,6 +25,7 @@
#ifndef SHARE_VM_RUNTIME_COMMANDLINEFLAGRANGELIST_HPP
#define SHARE_VM_RUNTIME_COMMANDLINEFLAGRANGELIST_HPP
#include "memory/metaspaceShared.hpp"
#include "runtime/globals.hpp"
#include "utilities/growableArray.hpp"

View File

@ -4110,21 +4110,26 @@ public:
"If PrintSharedArchiveAndExit is true, also print the shared " \
"dictionary") \
\
product(size_t, SharedReadWriteSize, NOT_LP64(12*M) LP64_ONLY(16*M), \
product(size_t, SharedReadWriteSize, DEFAULT_SHARED_READ_WRITE_SIZE, \
"Size of read-write space for metadata (in bytes)") \
range(MIN_SHARED_READ_WRITE_SIZE, MAX_SHARED_READ_WRITE_SIZE) \
\
product(size_t, SharedReadOnlySize, NOT_LP64(12*M) LP64_ONLY(16*M), \
product(size_t, SharedReadOnlySize, DEFAULT_SHARED_READ_ONLY_SIZE, \
"Size of read-only space for metadata (in bytes)") \
range(MIN_SHARED_READ_ONLY_SIZE, MAX_SHARED_READ_ONLY_SIZE) \
\
product(uintx, SharedMiscDataSize, NOT_LP64(2*M) LP64_ONLY(4*M), \
product(size_t, SharedMiscDataSize, DEFAULT_SHARED_MISC_DATA_SIZE, \
"Size of the shared miscellaneous data area (in bytes)") \
range(MIN_SHARED_MISC_DATA_SIZE, MAX_SHARED_MISC_DATA_SIZE) \
\
product(uintx, SharedMiscCodeSize, 120*K, \
product(size_t, SharedMiscCodeSize, DEFAULT_SHARED_MISC_CODE_SIZE, \
"Size of the shared miscellaneous code area (in bytes)") \
range(MIN_SHARED_MISC_CODE_SIZE, MAX_SHARED_MISC_CODE_SIZE) \
\
product(uintx, SharedBaseAddress, LP64_ONLY(32*G) \
product(size_t, SharedBaseAddress, LP64_ONLY(32*G) \
NOT_LP64(LINUX_ONLY(2*G) NOT_LINUX(0)), \
"Address to allocate shared memory region for class data") \
range(0, SIZE_MAX) \
\
product(uintx, SharedSymbolTableBucketSize, 4, \
"Average number of symbols per bucket in shared table") \

View File

@ -55,9 +55,28 @@ public class TestOptionsWithRanges {
* JDK-8136766
* Temporarily remove ThreadStackSize from testing because Windows can set it to 0
* (for default OS size) but other platforms insist it must be greater than 0
*/
*/
allOptionsAsMap.remove("ThreadStackSize");
/*
* JDK-8141650
* Temporarily exclude SharedMiscDataSize as it will exit the VM with exit code 2 and
* "The shared miscellaneous data space is not large enough to preload requested classes."
* message at min value.
*/
allOptionsAsMap.remove("SharedMiscDataSize");
/*
* JDK-8142874
* Temporarily exclude Shared* flagse as they will exit the VM with exit code 2 and
* "The shared miscellaneous data space is not large enough to preload requested classes."
* message at max values.
*/
allOptionsAsMap.remove("SharedReadWriteSize");
allOptionsAsMap.remove("SharedReadOnlySize");
allOptionsAsMap.remove("SharedMiscDataSize");
allOptionsAsMap.remove("SharedMiscCodeSize");
/*
* Exclude MallocMaxTestWords as it is expected to exit VM at small values (>=0)
*/

View File

@ -223,7 +223,7 @@ public class IntJVMOption extends JVMOption {
validValues.add("1");
}
if (max.compareTo(MAX_4_BYTE_INT_PLUS_ONE) == 1) {
if ((min.compareTo(MAX_4_BYTE_INT_PLUS_ONE) == -1) && (max.compareTo(MAX_4_BYTE_INT_PLUS_ONE) == 1)) {
/*
* Check for overflow when flag is assigned to the
* 4 byte int variable
@ -231,7 +231,7 @@ public class IntJVMOption extends JVMOption {
validValues.add(MAX_4_BYTE_INT_PLUS_ONE.toString());
}
if (max.compareTo(MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE) == 1) {
if ((min.compareTo(MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE) == -1) && (max.compareTo(MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE) == 1)) {
/*
* Check for overflow when flag is assigned to the
* 4 byte unsigned int variable

View File

@ -27,6 +27,7 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -49,6 +50,8 @@ public class JVMOptionsUtils {
/* Used to start the JVM with the same type as current */
static String VMType;
private static Map<String, JVMOption> optionsAsMap;
static {
if (Platform.isServer()) {
VMType = "-server";
@ -63,6 +66,84 @@ public class JVMOptionsUtils {
}
}
public static boolean fitsRange(String optionName, BigDecimal number) throws Exception {
JVMOption option;
String minRangeString = null;
String maxRangeString = null;
boolean fits = true;
if (optionsAsMap == null) {
optionsAsMap = getOptionsWithRangeAsMap();
}
option = optionsAsMap.get(optionName);
if (option != null) {
minRangeString = option.getMin();
if (minRangeString != null) {
fits = (number.compareTo(new BigDecimal(minRangeString)) >= 0);
}
maxRangeString = option.getMax();
if (maxRangeString != null) {
fits &= (number.compareTo(new BigDecimal(maxRangeString)) <= 0);
}
}
return fits;
}
public static boolean fitsRange(String optionName, String number) throws Exception {
String lowerCase = number.toLowerCase();
String multiplier = "1";
if (lowerCase.endsWith("k")) {
multiplier = "1024";
lowerCase = lowerCase.substring(0, lowerCase.length()-1);
} else if (lowerCase.endsWith("m")) {
multiplier = "1048576"; //1024*1024
lowerCase = lowerCase.substring(0, lowerCase.length()-1);
} else if (lowerCase.endsWith("g")) {
multiplier = "1073741824"; //1024*1024*1024
lowerCase = lowerCase.substring(0, lowerCase.length()-1);
} else if (lowerCase.endsWith("t")) {
multiplier = "1099511627776"; //1024*1024*1024*1024
lowerCase = lowerCase.substring(0, lowerCase.length()-1);
}
BigDecimal valueBig = new BigDecimal(lowerCase);
BigDecimal multiplierBig = new BigDecimal(multiplier);
return fitsRange(optionName, valueBig.multiply(multiplierBig));
}
public static String getMinOptionRange(String optionName) throws Exception {
JVMOption option;
String minRange = null;
if (optionsAsMap == null) {
optionsAsMap = getOptionsWithRangeAsMap();
}
option = optionsAsMap.get(optionName);
if (option != null) {
minRange = option.getMin();
}
return minRange;
}
public static String getMaxOptionRange(String optionName) throws Exception {
JVMOption option;
String maxRange = null;
if (optionsAsMap == null) {
optionsAsMap = getOptionsWithRangeAsMap();
}
option = optionsAsMap.get(optionName);
if (option != null) {
maxRange = option.getMax();
}
return maxRange;
}
/**
* Add dependency for option depending on it's name. E.g. enable G1 GC for
* G1 options or add prepend options to not hit constraints.
@ -80,6 +161,13 @@ public class JVMOptionsUtils {
option.addPrepend("-XX:+UseConcMarkSweepGC");
}
if (name.startsWith("Shared")) {
option.addPrepend("-XX:+UnlockDiagnosticVMOptions");
String fileName = "Test" + name + ".jsa";
option.addPrepend("-XX:SharedArchiveFile=" + fileName);
option.addPrepend("-Xshare:dump");
}
switch (name) {
case "MinHeapFreeRatio":
option.addPrepend("-XX:MaxHeapFreeRatio=100");
@ -112,7 +200,6 @@ public class JVMOptionsUtils {
/* Do nothing */
break;
}
}
/**

View File

@ -23,50 +23,72 @@
/* @test LimitSharedSizes
* @summary Test handling of limits on shared space size
* @library /testlibrary
* @library /testlibrary /runtime/CommandLine/OptionsValidation/common
* @modules java.base/sun.misc
* java.management
* @run main LimitSharedSizes
*/
import jdk.test.lib.*;
import optionsvalidation.JVMOptionsUtils;
public class LimitSharedSizes {
static enum Result {
OUT_OF_RANGE,
TOO_SMALL,
VALID,
VALID_ARCHIVE
}
static enum Region {
RO, RW, MD, MC
}
private static final boolean fitsRange(String name, String value) throws RuntimeException {
boolean fits = true;
try {
fits = JVMOptionsUtils.fitsRange(name, value);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return fits;
}
private static class SharedSizeTestData {
public String optionName;
public String optionValue;
public String expectedErrorMsg;
public Result optionResult;
public SharedSizeTestData(Region region, String value, String msg) {
optionName = getName(region);
public SharedSizeTestData(Region region, String value) {
optionName = "-XX:"+getName(region);
optionValue = value;
expectedErrorMsg = msg;
if (fitsRange(getName(region), value) == false) {
optionResult = Result.OUT_OF_RANGE;
} else {
optionResult = Result.TOO_SMALL;
}
}
public SharedSizeTestData(Region region, String msg) {
optionName = getName(region);
optionValue = getValue(region);
expectedErrorMsg = msg;
public SharedSizeTestData(Region region, String value, Result result) {
optionName = "-XX:"+getName(region);
optionValue = value;
optionResult = result;
}
private String getName(Region region) {
String name;
switch (region) {
case RO:
name = "-XX:SharedReadOnlySize";
name = "SharedReadOnlySize";
break;
case RW:
name = "-XX:SharedReadWriteSize";
name = "SharedReadWriteSize";
break;
case MD:
name = "-XX:SharedMiscDataSize";
name = "SharedMiscDataSize";
break;
case MC:
name = "-XX:SharedMiscCodeSize";
name = "SharedMiscCodeSize";
break;
default:
name = "Unknown";
@ -75,53 +97,37 @@ public class LimitSharedSizes {
return name;
}
private String getValue(Region region) {
String value;
switch (region) {
case RO:
value = Platform.is64bit() ? "9M" : "8M";
break;
case RW:
value = Platform.is64bit() ? "12M" : "7M";
break;
case MD:
value = Platform.is64bit() ? "4M" : "2M";
break;
case MC:
value = "120k";
break;
default:
value = "0M";
break;
}
return value;
public Result getResult() {
return optionResult;
}
}
private static final SharedSizeTestData[] testTable = {
// Too small of a region size should not cause a vm crash.
// It should result in an error message like the following:
// It should result in an error message either like the following #1:
// The shared miscellaneous code space is not large enough
// to preload requested classes. Use -XX:SharedMiscCodeSize=
// to increase the initial size of shared miscellaneous code space.
new SharedSizeTestData(Region.RO, "4M", "read only"),
new SharedSizeTestData(Region.RW, "4M", "read write"),
new SharedSizeTestData(Region.MD, "50k", "miscellaneous data"),
new SharedSizeTestData(Region.MC, "20k", "miscellaneous code"),
// or #2:
// The shared miscellaneous code space is outside the allowed range
new SharedSizeTestData(Region.RO, "4M"),
new SharedSizeTestData(Region.RW, "4M"),
new SharedSizeTestData(Region.MD, "50k"),
new SharedSizeTestData(Region.MC, "20k"),
// these values are larger than default ones, but should
// these values are larger than default ones, and should
// be acceptable and not cause failure
new SharedSizeTestData(Region.RO, "20M", null),
new SharedSizeTestData(Region.RW, "20M", null),
new SharedSizeTestData(Region.MD, "20M", null),
new SharedSizeTestData(Region.MC, "20M", null),
new SharedSizeTestData(Region.RO, "20M", Result.VALID),
new SharedSizeTestData(Region.RW, "20M", Result.VALID),
new SharedSizeTestData(Region.MD, "20M", Result.VALID),
new SharedSizeTestData(Region.MC, "20M", Result.VALID),
// test with sizes which just meet the minimum required sizes
// the following tests also attempt to use the shared archive
new SharedSizeTestData(Region.RO, "UseArchive"),
new SharedSizeTestData(Region.RW, "UseArchive"),
new SharedSizeTestData(Region.MD, "UseArchive"),
new SharedSizeTestData(Region.MC, "UseArchive")
new SharedSizeTestData(Region.RO, Platform.is64bit() ? "9M":"8M", Result.VALID_ARCHIVE),
new SharedSizeTestData(Region.RW, Platform.is64bit() ? "12M":"7M", Result.VALID_ARCHIVE),
new SharedSizeTestData(Region.MD, Platform.is64bit() ? "4M":"2M", Result.VALID_ARCHIVE),
new SharedSizeTestData(Region.MC, "120k", Result.VALID_ARCHIVE),
};
public static void main(String[] args) throws Exception {
@ -131,6 +137,7 @@ public class LimitSharedSizes {
counter++;
String option = td.optionName + "=" + td.optionValue;
System.out.println("testing option number <" + counter + ">");
System.out.println("testing option <" + option + ">");
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
@ -141,43 +148,52 @@ public class LimitSharedSizes {
OutputAnalyzer output = new OutputAnalyzer(pb.start());
if (td.expectedErrorMsg != null) {
if (!td.expectedErrorMsg.equals("UseArchive")) {
output.shouldContain("The shared " + td.expectedErrorMsg
+ " space is not large enough");
switch (td.getResult()) {
case VALID:
case VALID_ARCHIVE:
{
output.shouldNotContain("space is not large enough");
output.shouldHaveExitValue(0);
output.shouldHaveExitValue(2);
} else {
output.shouldNotContain("space is not large enough");
output.shouldHaveExitValue(0);
if (td.getResult() == Result.VALID_ARCHIVE) {
// try to use the archive
pb = ProcessTools.createJavaProcessBuilder(
"-XX:+UnlockDiagnosticVMOptions",
"-XX:SharedArchiveFile=./" + fileName,
"-XX:+PrintSharedArchiveAndExit",
"-version");
// try to use the archive
pb = ProcessTools.createJavaProcessBuilder(
"-XX:+UnlockDiagnosticVMOptions",
"-XX:SharedArchiveFile=./" + fileName,
"-XX:+PrintSharedArchiveAndExit",
"-version");
try {
output = new OutputAnalyzer(pb.start());
output.shouldContain("archive is valid");
} catch (RuntimeException e) {
// if sharing failed due to ASLR or similar reasons,
// check whether sharing was attempted at all (UseSharedSpaces)
if ((output.getOutput().contains("Unable to use shared archive") ||
output.getOutput().contains("Unable to map ReadOnly shared space at required address.") ||
output.getOutput().contains("Unable to map ReadWrite shared space at required address.") ||
output.getOutput().contains("Unable to reserve shared space at required address")) &&
output.getExitValue() == 1) {
System.out.println("Unable to use shared archive: test not executed; assumed passed");
return;
}
}
output.shouldHaveExitValue(0);
try {
output = new OutputAnalyzer(pb.start());
output.shouldContain("archive is valid");
} catch (RuntimeException e) {
// if sharing failed due to ASLR or similar reasons,
// check whether sharing was attempted at all (UseSharedSpaces)
if ((output.getOutput().contains("Unable to use shared archive") ||
output.getOutput().contains("Unable to map ReadOnly shared space at required address.") ||
output.getOutput().contains("Unable to map ReadWrite shared space at required address.") ||
output.getOutput().contains("Unable to reserve shared space at required address")) &&
output.getExitValue() == 1) {
System.out.println("Unable to use shared archive: test not executed; assumed passed");
return;
}
}
output.shouldHaveExitValue(0);
}
}
} else {
output.shouldNotContain("space is not large enough");
output.shouldHaveExitValue(0);
break;
case TOO_SMALL:
{
output.shouldContain("space is not large enough");
output.shouldHaveExitValue(2);
}
break;
case OUT_OF_RANGE:
{
output.shouldContain("outside the allowed range");
output.shouldHaveExitValue(1);
}
break;
}
}
}