Extend JVM options to support multiple versions
JDK 9 has removed JVM options that were valid in JDK 8 (e.g., GC logging flags) and replaced them with new flags that are not available in JDK 8. This means that a single JVM options file can no longer apply to JDK 8 and JDK 9, complicating development, complicating our packaging story, and complicating operations. This commit extends the JVM options syntax to specify the range of versions the option applies to. If the running JVM matches the range of versions, the flag will be used to start the JVM otherwise the flag will be ignored. We implement this parser in Java for simplicity, and with this we start our first step towards a Java launcher. Relates #27675
This commit is contained in:
parent
2aa62daed4
commit
6c7374804f
|
@ -164,7 +164,7 @@ configure(distributions) {
|
|||
from project(':core').jar
|
||||
from project(':core').configurations.runtime
|
||||
// delay add tools using closures, since they have not yet been configured, so no jar task exists yet
|
||||
from { project(':distribution:tools:java-version-checker').jar }
|
||||
from { project(':distribution:tools:launchers').jar }
|
||||
from { project(':distribution:tools:plugin-cli').jar }
|
||||
}
|
||||
|
||||
|
|
|
@ -16,15 +16,8 @@
|
|||
|
||||
source "`dirname "$0"`"/elasticsearch-env
|
||||
|
||||
parse_jvm_options() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "`grep "^-" "$1" | tr '\n' ' '`"
|
||||
fi
|
||||
}
|
||||
|
||||
ES_JVM_OPTIONS="$ES_PATH_CONF"/jvm.options
|
||||
|
||||
JVM_OPTIONS=`parse_jvm_options "$ES_JVM_OPTIONS"`
|
||||
JVM_OPTIONS=`"$JAVA" -cp "$ES_CLASSPATH" org.elasticsearch.tools.launchers.JvmOptionsParser "$ES_JVM_OPTIONS"`
|
||||
ES_JAVA_OPTS="${JVM_OPTIONS//\$\{ES_TMPDIR\}/$ES_TMPDIR} $ES_JAVA_OPTS"
|
||||
|
||||
cd "$ES_HOME"
|
||||
|
|
|
@ -63,7 +63,7 @@ if [ ! -z "$JAVA_OPTS" ]; then
|
|||
fi
|
||||
|
||||
# check the Java version
|
||||
"$JAVA" -cp "$ES_CLASSPATH" org.elasticsearch.tools.JavaVersionChecker
|
||||
"$JAVA" -cp "$ES_CLASSPATH" org.elasticsearch.tools.launchers.JavaVersionChecker
|
||||
|
||||
export HOSTNAME=$HOSTNAME
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ if defined JAVA_OPTS (
|
|||
)
|
||||
|
||||
rem check the Java version
|
||||
%JAVA% -cp "%ES_CLASSPATH%" "org.elasticsearch.tools.JavaVersionChecker" || exit /b 1
|
||||
%JAVA% -cp "%ES_CLASSPATH%" "org.elasticsearch.tools.launchers.JavaVersionChecker" || exit /b 1
|
||||
|
||||
set HOSTNAME=%COMPUTERNAME%
|
||||
|
||||
|
|
|
@ -103,11 +103,19 @@ set ES_JVM_OPTIONS=%ES_PATH_CONF%\jvm.options
|
|||
if not "%ES_JAVA_OPTS%" == "" set ES_JAVA_OPTS=%ES_JAVA_OPTS: =;%
|
||||
|
||||
@setlocal
|
||||
for /F "usebackq delims=" %%a in (`findstr /b \- "%ES_JVM_OPTIONS%" ^| findstr /b /v "\-server \-client"`) do set JVM_OPTIONS=!JVM_OPTIONS!%%a;
|
||||
@endlocal & set ES_JAVA_OPTS=%JVM_OPTIONS:${ES_TMPDIR}=!ES_TMPDIR!%%ES_JAVA_OPTS%
|
||||
for /F "usebackq delims=" %%a in (`"%JAVA% -cp "%ES_CLASSPATH%" "org.elasticsearch.tools.launchers.JvmOptionsParser" "%ES_JVM_OPTIONS%" || echo jvm_options_parser_failed"`) do set JVM_OPTIONS=%%a
|
||||
@endlocal & set "MAYBE_JVM_OPTIONS_PARSER_FAILED=%JVM_OPTIONS%" & set ES_JAVA_OPTS=%JVM_OPTIONS:${ES_TMPDIR}=!ES_TMPDIR!% %ES_JAVA_OPTS%
|
||||
|
||||
if "%MAYBE_JVM_OPTIONS_PARSER_FAILED%" == "jvm_options_parser_failed" (
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not "%ES_JAVA_OPTS%" == "" set ES_JAVA_OPTS=%ES_JAVA_OPTS: =;%
|
||||
|
||||
if "%ES_JAVA_OPTS:~-1%"==";" set ES_JAVA_OPTS=%ES_JAVA_OPTS:~0,-1%
|
||||
|
||||
echo %ES_JAVA_OPTS%
|
||||
|
||||
@setlocal EnableDelayedExpansion
|
||||
for %%a in ("%ES_JAVA_OPTS:;=","%") do (
|
||||
set var=%%a
|
||||
|
|
|
@ -42,12 +42,13 @@ IF ERRORLEVEL 1 (
|
|||
)
|
||||
|
||||
set "ES_JVM_OPTIONS=%ES_PATH_CONF%\jvm.options"
|
||||
|
||||
@setlocal
|
||||
rem extract the options from the JVM options file %ES_JVM_OPTIONS%
|
||||
rem such options are the lines beginning with '-', thus "findstr /b"
|
||||
for /F "usebackq delims=" %%a in (`findstr /b \- "%ES_JVM_OPTIONS%"`) do set JVM_OPTIONS=!JVM_OPTIONS! %%a
|
||||
@endlocal & set ES_JAVA_OPTS=%JVM_OPTIONS:${ES_TMPDIR}=!ES_TMPDIR!% %ES_JAVA_OPTS%
|
||||
for /F "usebackq delims=" %%a in (`"%JAVA% -cp "%ES_CLASSPATH%" "org.elasticsearch.tools.launchers.JvmOptionsParser" "%ES_JVM_OPTIONS%" || echo jvm_options_parser_failed"`) do set JVM_OPTIONS=%%a
|
||||
@endlocal & set "MAYBE_JVM_OPTIONS_PARSER_FAILED=%JVM_OPTIONS%" & set ES_JAVA_OPTS=%JVM_OPTIONS:${ES_TMPDIR}=!ES_TMPDIR!% %ES_JAVA_OPTS%
|
||||
|
||||
if "%MAYBE_JVM_OPTIONS_PARSER_FAILED%" == "jvm_options_parser_failed" (
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
cd "%ES_HOME%"
|
||||
%JAVA% %ES_JAVA_OPTS% -Delasticsearch -Des.path.home="%ES_HOME%" -Des.path.conf="%ES_PATH_CONF%" -cp "%ES_CLASSPATH%" "org.elasticsearch.bootstrap.Elasticsearch" !newparams!
|
||||
|
|
|
@ -44,9 +44,6 @@
|
|||
|
||||
## basic
|
||||
|
||||
# force the server VM
|
||||
-server
|
||||
|
||||
# explicitly set the stack size
|
||||
-Xss1m
|
||||
|
||||
|
@ -84,13 +81,16 @@
|
|||
# ensure the directory exists and has sufficient space
|
||||
${heap.dump.path}
|
||||
|
||||
## GC logging
|
||||
## JDK 8 GC logging
|
||||
|
||||
-XX:+PrintGCDetails
|
||||
-XX:+PrintGCDateStamps
|
||||
-XX:+PrintTenuringDistribution
|
||||
-XX:+PrintGCApplicationStoppedTime
|
||||
-Xloggc:${loggc}
|
||||
-XX:+UseGCLogFileRotation
|
||||
-XX:NumberOfGCLogFiles=32
|
||||
-XX:GCLogFileSize=64m
|
||||
8:-XX:+PrintGCDetails
|
||||
8:-XX:+PrintGCDateStamps
|
||||
8:-XX:+PrintTenuringDistribution
|
||||
8:-XX:+PrintGCApplicationStoppedTime
|
||||
8:-Xloggc:${loggc}
|
||||
8:-XX:+UseGCLogFileRotation
|
||||
8:-XX:NumberOfGCLogFiles=32
|
||||
8:-XX:GCLogFileSize=64m
|
||||
|
||||
# JDK 9+ GC logging
|
||||
9-:-Xlog:gc*,gc+age=trace,safepoint:file=${loggc}:utctime,pid,tags:filecount=32,filesize=64m
|
||||
|
|
|
@ -17,26 +17,38 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
import org.elasticsearch.gradle.precommit.PrecommitTasks
|
||||
import org.gradle.api.JavaVersion
|
||||
|
||||
apply plugin: 'elasticsearch.build'
|
||||
apply plugin: 'ru.vyarus.animalsniffer'
|
||||
|
||||
sourceCompatibility = JavaVersion.VERSION_1_6
|
||||
targetCompatibility = JavaVersion.VERSION_1_6
|
||||
sourceCompatibility = JavaVersion.VERSION_1_7
|
||||
targetCompatibility = JavaVersion.VERSION_1_7
|
||||
|
||||
dependencies {
|
||||
signature "org.codehaus.mojo.signature:java16:1.0@signature"
|
||||
signature "org.codehaus.mojo.signature:java17:1.0@signature"
|
||||
|
||||
testCompile "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.randomizedrunner}"
|
||||
testCompile "junit:junit:${versions.junit}"
|
||||
testCompile "org.hamcrest:hamcrest-all:${versions.hamcrest}"
|
||||
}
|
||||
|
||||
archivesBaseName = 'elasticsearch-launchers'
|
||||
|
||||
// launchers do not depend on core so only JDK signatures should be checked
|
||||
forbiddenApisMain {
|
||||
// java-version-checker does not depend on core so only JDK signatures should be checked
|
||||
signaturesURLs = [PrecommitTasks.getResource('/forbidden/jdk-signatures.txt')]
|
||||
}
|
||||
forbiddenApisTest {
|
||||
signaturesURLs = [PrecommitTasks.getResource('/forbidden/jdk-signatures.txt')]
|
||||
}
|
||||
|
||||
namingConventions {
|
||||
testClass = 'org.elasticsearch.tools.launchers.LaunchersTestCase'
|
||||
skipIntegTestInDisguise = true
|
||||
}
|
||||
|
||||
javadoc.enabled = false
|
||||
test.enabled = false
|
||||
loggerUsageCheck.enabled = false
|
||||
jarHell.enabled=false
|
|
@ -17,47 +17,18 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.tools;
|
||||
package org.elasticsearch.tools.launchers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Simple program that checks if the runtime Java version is at least 1.8.
|
||||
*/
|
||||
final class JavaVersionChecker {
|
||||
public class JavaVersion {
|
||||
|
||||
private JavaVersionChecker() {
|
||||
}
|
||||
static final List<Integer> CURRENT = parse(System.getProperty("java.specification.version"));
|
||||
static final List<Integer> JAVA_8 = parse("1.8");
|
||||
|
||||
private static final List<Integer> JAVA_8 = Arrays.asList(1, 8);
|
||||
|
||||
/**
|
||||
* The main entry point. The exit code is 0 if the Java version is at least 1.8, otherwise the exit code is 1.
|
||||
*
|
||||
* @param args the args to the program which are rejected if not empty
|
||||
*/
|
||||
public static void main(final String[] args) {
|
||||
// no leniency!
|
||||
if (args.length != 0) {
|
||||
throw new IllegalArgumentException("expected zero arguments but was: " + Arrays.toString(args));
|
||||
}
|
||||
final String javaSpecificationVersion = System.getProperty("java.specification.version");
|
||||
final List<Integer> current = parse(javaSpecificationVersion);
|
||||
if (compare(current, JAVA_8) < 0) {
|
||||
final String message = String.format(
|
||||
Locale.ROOT,
|
||||
"the minimum required Java version is 8; your Java version from [%s] does not meet this requirement",
|
||||
System.getProperty("java.home"));
|
||||
println(message);
|
||||
exit(1);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
private static List<Integer> parse(final String value) {
|
||||
static List<Integer> parse(final String value) {
|
||||
if (!value.matches("^0*[0-9]+(\\.[0-9]+)*$")) {
|
||||
throw new IllegalArgumentException(value);
|
||||
}
|
||||
|
@ -70,7 +41,16 @@ final class JavaVersionChecker {
|
|||
return version;
|
||||
}
|
||||
|
||||
private static int compare(final List<Integer> left, final List<Integer> right) {
|
||||
static int majorVersion(final List<Integer> javaVersion) {
|
||||
Objects.requireNonNull(javaVersion);
|
||||
if (javaVersion.get(0) > 1) {
|
||||
return javaVersion.get(0);
|
||||
} else {
|
||||
return javaVersion.get(1);
|
||||
}
|
||||
}
|
||||
|
||||
static int compare(final List<Integer> left, final List<Integer> right) {
|
||||
// lexicographically compare two lists, treating missing entries as zeros
|
||||
final int len = Math.max(left.size(), right.size());
|
||||
for (int i = 0; i < len; i++) {
|
||||
|
@ -86,14 +66,5 @@ final class JavaVersionChecker {
|
|||
return 0;
|
||||
}
|
||||
|
||||
@SuppressForbidden(reason = "System#err")
|
||||
private static void println(String message) {
|
||||
System.err.println(message);
|
||||
}
|
||||
|
||||
@SuppressForbidden(reason = "System#exit")
|
||||
private static void exit(final int status) {
|
||||
System.exit(status);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.tools.launchers;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Simple program that checks if the runtime Java version is at least 1.8.
|
||||
*/
|
||||
final class JavaVersionChecker {
|
||||
|
||||
private JavaVersionChecker() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The main entry point. The exit code is 0 if the Java version is at least 1.8, otherwise the exit code is 1.
|
||||
*
|
||||
* @param args the args to the program which are rejected if not empty
|
||||
*/
|
||||
public static void main(final String[] args) {
|
||||
// no leniency!
|
||||
if (args.length != 0) {
|
||||
throw new IllegalArgumentException("expected zero arguments but was " + Arrays.toString(args));
|
||||
}
|
||||
if (JavaVersion.compare(JavaVersion.CURRENT, JavaVersion.JAVA_8) < 0) {
|
||||
final String message = String.format(
|
||||
Locale.ROOT,
|
||||
"the minimum required Java version is 8; your Java version from [%s] does not meet this requirement",
|
||||
System.getProperty("java.home"));
|
||||
Launchers.errPrintln(message);
|
||||
Launchers.exit(1);
|
||||
}
|
||||
Launchers.exit(0);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.tools.launchers;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Parses JVM options from a file and prints a single line with all JVM options to standard output.
|
||||
*/
|
||||
final class JvmOptionsParser {
|
||||
|
||||
/**
|
||||
* The main entry point. The exit code is 0 if the JVM options were successfully parsed, otherwise the exit code is 1. If an improperly
|
||||
* formatted line is discovered, the line is output to standard error.
|
||||
*
|
||||
* @param args the args to the program which should consist of a single option, the path to the JVM options
|
||||
*/
|
||||
public static void main(final String[] args) throws IOException {
|
||||
if (args.length != 1) {
|
||||
throw new IllegalArgumentException("expected one argument specifying path to jvm.options but was " + Arrays.toString(args));
|
||||
}
|
||||
final List<String> jvmOptions = new ArrayList<>();
|
||||
final SortedMap<Integer, String> invalidLines = new TreeMap<>();
|
||||
try (InputStream is = Files.newInputStream(Paths.get(args[0]));
|
||||
Reader reader = new InputStreamReader(is, Charset.forName("UTF-8"));
|
||||
BufferedReader br = new BufferedReader(reader)) {
|
||||
parse(
|
||||
JavaVersion.majorVersion(JavaVersion.CURRENT),
|
||||
br,
|
||||
new JvmOptionConsumer() {
|
||||
@Override
|
||||
public void accept(final String jvmOption) {
|
||||
jvmOptions.add(jvmOption);
|
||||
}
|
||||
},
|
||||
new InvalidLineConsumer() {
|
||||
@Override
|
||||
public void accept(final int lineNumber, final String line) {
|
||||
invalidLines.put(lineNumber, line);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (invalidLines.isEmpty()) {
|
||||
final String spaceDelimitedJvmOptions = spaceDelimitJvmOptions(jvmOptions);
|
||||
Launchers.outPrintln(spaceDelimitedJvmOptions);
|
||||
Launchers.exit(0);
|
||||
} else {
|
||||
final String errorMessage = String.format(
|
||||
Locale.ROOT,
|
||||
"encountered [%d] error%s parsing [%s]",
|
||||
invalidLines.size(),
|
||||
invalidLines.size() == 1 ? "" : "s",
|
||||
args[0]);
|
||||
Launchers.errPrintln(errorMessage);
|
||||
int count = 0;
|
||||
for (final Map.Entry<Integer, String> entry : invalidLines.entrySet()) {
|
||||
count++;
|
||||
final String message = String.format(
|
||||
Locale.ROOT,
|
||||
"[%d]: encountered improperly formatted JVM option line [%s] on line number [%d]",
|
||||
count,
|
||||
entry.getValue(),
|
||||
entry.getKey());
|
||||
Launchers.errPrintln(message);
|
||||
}
|
||||
Launchers.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for valid JVM options.
|
||||
*/
|
||||
interface JvmOptionConsumer {
|
||||
/**
|
||||
* Invoked when a line in the JVM options file matches the specified syntax and the specified major version.
|
||||
* @param jvmOption the matching JVM option
|
||||
*/
|
||||
void accept(String jvmOption);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for invalid lines in the JVM options.
|
||||
*/
|
||||
interface InvalidLineConsumer {
|
||||
/**
|
||||
* Invoked when a line in the JVM options does not match the specified syntax.
|
||||
*/
|
||||
void accept(int lineNumber, String line);
|
||||
}
|
||||
|
||||
private static final Pattern PATTERN = Pattern.compile("((?<start>\\d+)(?<range>-)?(?<end>\\d+)?:)?(?<option>-.*)$");
|
||||
|
||||
/**
|
||||
* Parse the line-delimited JVM options from the specified buffered reader for the specified Java major version.
|
||||
* Valid JVM options are:
|
||||
* <ul>
|
||||
* <li>
|
||||
* a line starting with a dash is treated as a JVM option that applies to all versions
|
||||
* </li>
|
||||
* <li>
|
||||
* a line starting with a number followed by a colon is treated as a JVM option that applies to the matching Java major version
|
||||
* only
|
||||
* </li>
|
||||
* <li>
|
||||
* a line starting with a number followed by a dash is treated as a JVM option that applies to the matching Java specified major
|
||||
* version and all larger Java major versions
|
||||
* </li>
|
||||
* <li>
|
||||
* a line starting with a number followed by a dash followed by a number is treated as a JVM option that applies to the
|
||||
* specified range of matching Java major versions
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* For example, if the specified Java major version is 8, the following JVM options will be accepted:
|
||||
* <ul>
|
||||
* <li>
|
||||
* {@code -XX:+PrintGCDateStamps}
|
||||
* </li>
|
||||
* <li>
|
||||
* {@code 8:-XX:+PrintGCDateStamps}
|
||||
* </li>
|
||||
* <li>
|
||||
* {@code 8-:-XX:+PrintGCDateStamps}
|
||||
* </li>
|
||||
* <li>
|
||||
* {@code 7-8:-XX:+PrintGCDateStamps}
|
||||
* </li>
|
||||
* </ul>
|
||||
* and the following JVM options will not be accepted:
|
||||
* <ul>
|
||||
* <li>
|
||||
* {@code 9:-Xlog:age*=trace,gc*,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m}
|
||||
* </li>
|
||||
* <li>
|
||||
* {@code 9-:-Xlog:age*=trace,gc*,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m}
|
||||
* </li>
|
||||
* <li>
|
||||
* {@code 9-10:-Xlog:age*=trace,gc*,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m}
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* If the version syntax specified on a line matches the specified JVM options, the JVM option callback will be invoked with the JVM
|
||||
* option. If the line does not match the specified syntax for the JVM options, the invalid line callback will be invoked with the
|
||||
* contents of the entire line.
|
||||
*
|
||||
* @param javaMajorVersion the Java major version to match JVM options against
|
||||
* @param br the buffered reader to read line-delimited JVM options from
|
||||
* @param jvmOptionConsumer the callback that accepts matching JVM options
|
||||
* @param invalidLineConsumer a callback that accepts invalid JVM options
|
||||
* @throws IOException if an I/O exception occurs reading from the buffered reader
|
||||
*/
|
||||
static void parse(
|
||||
final int javaMajorVersion,
|
||||
final BufferedReader br,
|
||||
final JvmOptionConsumer jvmOptionConsumer,
|
||||
final InvalidLineConsumer invalidLineConsumer) throws IOException {
|
||||
int lineNumber = 0;
|
||||
while (true) {
|
||||
final String line = br.readLine();
|
||||
lineNumber++;
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
if (line.startsWith("#")) {
|
||||
// lines beginning with "#" are treated as comments
|
||||
continue;
|
||||
}
|
||||
if (line.matches("\\s*")) {
|
||||
// skip blank lines
|
||||
continue;
|
||||
}
|
||||
final Matcher matcher = PATTERN.matcher(line);
|
||||
if (matcher.matches()) {
|
||||
final String start = matcher.group("start");
|
||||
final String end = matcher.group("end");
|
||||
if (start == null) {
|
||||
// no range present, unconditionally apply the JVM option
|
||||
jvmOptionConsumer.accept(line);
|
||||
} else {
|
||||
final int lower;
|
||||
try {
|
||||
lower = Integer.parseInt(start);
|
||||
} catch (final NumberFormatException e) {
|
||||
invalidLineConsumer.accept(lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
final int upper;
|
||||
if (matcher.group("range") == null) {
|
||||
// no range is present, apply the JVM option to the specified major version only
|
||||
upper = lower;
|
||||
} else if (end == null) {
|
||||
// a range of the form \\d+- is present, apply the JVM option to all major versions larger than the specifed one
|
||||
upper = Integer.MAX_VALUE;
|
||||
} else {
|
||||
// a range of the form \\d+-\\d+ is present, apply the JVM option to the specified range of major versions
|
||||
try {
|
||||
upper = Integer.parseInt(end);
|
||||
} catch (final NumberFormatException e) {
|
||||
invalidLineConsumer.accept(lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
if (upper < lower) {
|
||||
invalidLineConsumer.accept(lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (lower <= javaMajorVersion && javaMajorVersion <= upper) {
|
||||
jvmOptionConsumer.accept(matcher.group("option"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
invalidLineConsumer.accept(lineNumber, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delimits the specified JVM options by spaces.
|
||||
*
|
||||
* @param jvmOptions the JVM options
|
||||
* @return a single-line string containing the specified JVM options in the order they appear delimited by spaces
|
||||
*/
|
||||
static String spaceDelimitJvmOptions(final List<String> jvmOptions) {
|
||||
final StringBuilder spaceDelimitedJvmOptionsBuilder = new StringBuilder();
|
||||
final Iterator<String> it = jvmOptions.iterator();
|
||||
while (it.hasNext()) {
|
||||
spaceDelimitedJvmOptionsBuilder.append(it.next());
|
||||
if (it.hasNext()) {
|
||||
spaceDelimitedJvmOptionsBuilder.append(" ");
|
||||
}
|
||||
}
|
||||
return spaceDelimitedJvmOptionsBuilder.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.tools.launchers;
|
||||
|
||||
/**
|
||||
* Utility methods for launchers.
|
||||
*/
|
||||
final class Launchers {
|
||||
|
||||
/**
|
||||
* Prints a string and terminates the line on standard output.
|
||||
*
|
||||
* @param message the message to print
|
||||
*/
|
||||
@SuppressForbidden(reason = "System#out")
|
||||
static void outPrintln(final String message) {
|
||||
System.out.println(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a string and terminates the line on standard error.
|
||||
*
|
||||
* @param message the message to print
|
||||
*/
|
||||
@SuppressForbidden(reason = "System#err")
|
||||
static void errPrintln(final String message) {
|
||||
System.err.println(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit the VM with the specified status.
|
||||
*
|
||||
* @param status the status
|
||||
*/
|
||||
@SuppressForbidden(reason = "System#exit")
|
||||
static void exit(final int status) {
|
||||
System.exit(status);
|
||||
}
|
||||
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.tools;
|
||||
package org.elasticsearch.tools.launchers;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.tools.launchers;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class JvmOptionsParserTests extends LaunchersTestCase {
|
||||
|
||||
public void testUnversionedOptions() throws IOException {
|
||||
try (StringReader sr = new StringReader("-Xms1g\n-Xmx1g");
|
||||
BufferedReader br = new BufferedReader(sr)) {
|
||||
assertExpectedJvmOptions(randomIntBetween(8, Integer.MAX_VALUE), br, Arrays.asList("-Xms1g", "-Xmx1g"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testSingleVersionOption() throws IOException {
|
||||
final int javaMajorVersion = randomIntBetween(8, Integer.MAX_VALUE - 1);
|
||||
final int smallerJavaMajorVersion = randomIntBetween(7, javaMajorVersion);
|
||||
final int largerJavaMajorVersion = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE);
|
||||
try (StringReader sr = new StringReader(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"-Xms1g\n%d:-Xmx1g\n%d:-XX:+UseG1GC\n%d:-Xlog:gc",
|
||||
javaMajorVersion,
|
||||
smallerJavaMajorVersion,
|
||||
largerJavaMajorVersion));
|
||||
BufferedReader br = new BufferedReader(sr)) {
|
||||
assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnboundedVersionOption() throws IOException {
|
||||
final int javaMajorVersion = randomIntBetween(8, Integer.MAX_VALUE - 1);
|
||||
final int smallerJavaMajorVersion = randomIntBetween(7, javaMajorVersion);
|
||||
final int largerJavaMajorVersion = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE);
|
||||
try (StringReader sr = new StringReader(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"-Xms1g\n%d-:-Xmx1g\n%d-:-XX:+UseG1GC\n%d-:-Xlog:gc",
|
||||
javaMajorVersion,
|
||||
smallerJavaMajorVersion,
|
||||
largerJavaMajorVersion));
|
||||
BufferedReader br = new BufferedReader(sr)) {
|
||||
assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g", "-XX:+UseG1GC"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testBoundedVersionOption() throws IOException {
|
||||
final int javaMajorVersion = randomIntBetween(8, Integer.MAX_VALUE - 1);
|
||||
final int javaMajorVersionUpperBound = randomIntBetween(javaMajorVersion, Integer.MAX_VALUE - 1);
|
||||
final int smallerJavaMajorVersionLowerBound = randomIntBetween(7, javaMajorVersion);
|
||||
final int smallerJavaMajorVersionUpperBound = randomIntBetween(smallerJavaMajorVersionLowerBound, javaMajorVersion);
|
||||
final int largerJavaMajorVersionLowerBound = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE);
|
||||
final int largerJavaMajorVersionUpperBound = randomIntBetween(largerJavaMajorVersionLowerBound, Integer.MAX_VALUE);
|
||||
try (StringReader sr = new StringReader(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"-Xms1g\n%d-%d:-Xmx1g\n%d-%d:-XX:+UseG1GC\n%d-%d:-Xlog:gc",
|
||||
javaMajorVersion,
|
||||
javaMajorVersionUpperBound,
|
||||
smallerJavaMajorVersionLowerBound,
|
||||
smallerJavaMajorVersionUpperBound,
|
||||
largerJavaMajorVersionLowerBound,
|
||||
largerJavaMajorVersionUpperBound));
|
||||
BufferedReader br = new BufferedReader(sr)) {
|
||||
assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testComplexOptions() throws IOException {
|
||||
final int javaMajorVersion = randomIntBetween(8, Integer.MAX_VALUE - 1);
|
||||
final int javaMajorVersionUpperBound = randomIntBetween(javaMajorVersion, Integer.MAX_VALUE - 1);
|
||||
final int smallerJavaMajorVersionLowerBound = randomIntBetween(7, javaMajorVersion);
|
||||
final int smallerJavaMajorVersionUpperBound = randomIntBetween(smallerJavaMajorVersionLowerBound, javaMajorVersion);
|
||||
final int largerJavaMajorVersionLowerBound = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE);
|
||||
final int largerJavaMajorVersionUpperBound = randomIntBetween(largerJavaMajorVersionLowerBound, Integer.MAX_VALUE);
|
||||
try (StringReader sr = new StringReader(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"-Xms1g\n%d:-Xmx1g\n%d-:-XX:+UseG1GC\n%d-%d:-Xlog:gc\n%d-%d:-XX:+PrintFlagsFinal\n%d-%d:-XX+AggressiveOpts",
|
||||
javaMajorVersion,
|
||||
javaMajorVersion,
|
||||
javaMajorVersion,
|
||||
javaMajorVersionUpperBound,
|
||||
smallerJavaMajorVersionLowerBound,
|
||||
smallerJavaMajorVersionUpperBound,
|
||||
largerJavaMajorVersionLowerBound,
|
||||
largerJavaMajorVersionUpperBound));
|
||||
BufferedReader br = new BufferedReader(sr)) {
|
||||
assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g", "-XX:+UseG1GC", "-Xlog:gc"));
|
||||
}
|
||||
}
|
||||
|
||||
private void assertExpectedJvmOptions(
|
||||
final int javaMajorVersion, final BufferedReader br, final List<String> expectedJvmOptions) throws IOException {
|
||||
final Map<String, AtomicBoolean> seenJvmOptions = new HashMap<>();
|
||||
for (final String expectedJvmOption : expectedJvmOptions) {
|
||||
assertNull(seenJvmOptions.put(expectedJvmOption, new AtomicBoolean()));
|
||||
}
|
||||
JvmOptionsParser.parse(
|
||||
javaMajorVersion,
|
||||
br,
|
||||
new JvmOptionsParser.JvmOptionConsumer() {
|
||||
@Override
|
||||
public void accept(final String jvmOption) {
|
||||
final AtomicBoolean seen = seenJvmOptions.get(jvmOption);
|
||||
if (seen == null) {
|
||||
fail("unexpected JVM option [" + jvmOption + "]");
|
||||
}
|
||||
assertFalse("saw JVM option [" + jvmOption + "] more than once", seen.get());
|
||||
seen.set(true);
|
||||
}
|
||||
},
|
||||
new JvmOptionsParser.InvalidLineConsumer() {
|
||||
@Override
|
||||
public void accept(final int lineNumber, final String line) {
|
||||
fail("unexpected invalid line [" + line + "] on line number [" + lineNumber + "]");
|
||||
}
|
||||
});
|
||||
for (final Map.Entry<String, AtomicBoolean> seenJvmOption : seenJvmOptions.entrySet()) {
|
||||
assertTrue("expected JVM option [" + seenJvmOption.getKey() + "]", seenJvmOption.getValue().get());
|
||||
}
|
||||
}
|
||||
|
||||
public void testInvalidLines() throws IOException {
|
||||
try (StringReader sr = new StringReader("XX:+UseG1GC");
|
||||
BufferedReader br = new BufferedReader(sr)) {
|
||||
JvmOptionsParser.parse(
|
||||
randomIntBetween(8, Integer.MAX_VALUE),
|
||||
br,
|
||||
new JvmOptionsParser.JvmOptionConsumer() {
|
||||
@Override
|
||||
public void accept(final String jvmOption) {
|
||||
fail("unexpected valid JVM option [" + jvmOption + "]");
|
||||
}
|
||||
}, new JvmOptionsParser.InvalidLineConsumer() {
|
||||
@Override
|
||||
public void accept(final int lineNumber, final String line) {
|
||||
assertThat(lineNumber, equalTo(1));
|
||||
assertThat(line, equalTo("XX:+UseG1GC"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final int javaMajorVersion = randomIntBetween(8, Integer.MAX_VALUE);
|
||||
final int smallerJavaMajorVersion = randomIntBetween(7, javaMajorVersion - 1);
|
||||
final String invalidRangeLine = String.format(Locale.ROOT, "%d:%d-XX:+UseG1GC", javaMajorVersion, smallerJavaMajorVersion);
|
||||
try (StringReader sr = new StringReader(invalidRangeLine);
|
||||
BufferedReader br = new BufferedReader(sr)) {
|
||||
assertInvalidLines(br, Collections.singletonMap(1, invalidRangeLine));
|
||||
}
|
||||
|
||||
final long invalidLowerJavaMajorVersion = (long) randomIntBetween(1, 16) + Integer.MAX_VALUE;
|
||||
final long invalidUpperJavaMajorVersion = (long) randomIntBetween(1, 16) + Integer.MAX_VALUE;
|
||||
final String numberFormatExceptionsLine = String.format(
|
||||
Locale.ROOT,
|
||||
"%d:-XX:+UseG1GC\n8-%d:-XX:+AggressiveOpts",
|
||||
invalidLowerJavaMajorVersion,
|
||||
invalidUpperJavaMajorVersion);
|
||||
try (StringReader sr = new StringReader(numberFormatExceptionsLine);
|
||||
BufferedReader br = new BufferedReader(sr)) {
|
||||
final Map<Integer, String> invalidLines = new HashMap<>(2);
|
||||
invalidLines.put(1, String.format(Locale.ROOT, "%d:-XX:+UseG1GC", invalidLowerJavaMajorVersion));
|
||||
invalidLines.put(2, String.format(Locale.ROOT, "8-%d:-XX:+AggressiveOpts", invalidUpperJavaMajorVersion));
|
||||
assertInvalidLines(br, invalidLines);
|
||||
}
|
||||
|
||||
final String multipleInvalidLines = "XX:+UseG1GC\nXX:+AggressiveOpts";
|
||||
try (StringReader sr = new StringReader(multipleInvalidLines);
|
||||
BufferedReader br = new BufferedReader(sr)) {
|
||||
final Map<Integer, String> invalidLines = new HashMap<>(2);
|
||||
invalidLines.put(1, "XX:+UseG1GC");
|
||||
invalidLines.put(2, "XX:+AggressiveOpts");
|
||||
assertInvalidLines(br, invalidLines);
|
||||
}
|
||||
|
||||
final int lowerBound = randomIntBetween(9, 16);
|
||||
final int upperBound = randomIntBetween(8, lowerBound - 1);
|
||||
final String upperBoundGreaterThanLowerBound = String.format(Locale.ROOT, "%d-%d-XX:+UseG1GC", lowerBound, upperBound);
|
||||
try (StringReader sr = new StringReader(upperBoundGreaterThanLowerBound);
|
||||
BufferedReader br = new BufferedReader(sr)) {
|
||||
assertInvalidLines(br, Collections.singletonMap(1, upperBoundGreaterThanLowerBound));
|
||||
}
|
||||
}
|
||||
|
||||
private void assertInvalidLines(final BufferedReader br, final Map<Integer, String> invalidLines) throws IOException {
|
||||
final Map<Integer, String> seenInvalidLines = new HashMap<>(invalidLines.size());
|
||||
JvmOptionsParser.parse(
|
||||
randomIntBetween(8, Integer.MAX_VALUE),
|
||||
br,
|
||||
new JvmOptionsParser.JvmOptionConsumer() {
|
||||
@Override
|
||||
public void accept(final String jvmOption) {
|
||||
fail("unexpected valid JVM options [" + jvmOption + "]");
|
||||
}
|
||||
},
|
||||
new JvmOptionsParser.InvalidLineConsumer() {
|
||||
@Override
|
||||
public void accept(final int lineNumber, final String line) {
|
||||
seenInvalidLines.put(lineNumber, line);
|
||||
}
|
||||
});
|
||||
assertThat(seenInvalidLines, equalTo(invalidLines));
|
||||
}
|
||||
|
||||
public void testSpaceDelimitedJvmOptions() {
|
||||
assertThat(JvmOptionsParser.spaceDelimitJvmOptions(Collections.singletonList("-Xms1g")), equalTo("-Xms1g"));
|
||||
assertThat(JvmOptionsParser.spaceDelimitJvmOptions(Arrays.asList("-Xms1g", "-Xmx1g")), equalTo("-Xms1g -Xmx1g"));
|
||||
assertThat(
|
||||
JvmOptionsParser.spaceDelimitJvmOptions(Arrays.asList("-Xms1g", "-Xmx1g", "-XX:+UseG1GC")),
|
||||
equalTo("-Xms1g -Xmx1g -XX:+UseG1GC"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.tools.launchers;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.JUnit3MethodProvider;
|
||||
import com.carrotsearch.randomizedtesting.MixWithSuiteName;
|
||||
import com.carrotsearch.randomizedtesting.RandomizedTest;
|
||||
import com.carrotsearch.randomizedtesting.annotations.SeedDecorators;
|
||||
import com.carrotsearch.randomizedtesting.annotations.TestMethodProviders;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakAction;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakGroup;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies;
|
||||
import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite;
|
||||
|
||||
@TestMethodProviders({
|
||||
JUnit3MethodProvider.class
|
||||
})
|
||||
@SeedDecorators({MixWithSuiteName.class})
|
||||
@ThreadLeakScope(ThreadLeakScope.Scope.SUITE)
|
||||
@ThreadLeakGroup(ThreadLeakGroup.Group.MAIN)
|
||||
@ThreadLeakAction({ThreadLeakAction.Action.WARN, ThreadLeakAction.Action.INTERRUPT})
|
||||
@ThreadLeakZombies(ThreadLeakZombies.Consequence.IGNORE_REMAINING_TESTS)
|
||||
@ThreadLeakLingering(linger = 5000)
|
||||
@TimeoutSuite(millis = 2 * 60 * 60 * 1000)
|
||||
abstract class LaunchersTestCase extends RandomizedTest {
|
||||
}
|
|
@ -119,8 +119,25 @@ system properties and JVM flags) is via the `jvm.options` configuration
|
|||
file. The default location of this file is `config/jvm.options` (when
|
||||
installing from the tar or zip distributions) and
|
||||
`/etc/elasticsearch/jvm.options` (when installing from the Debian or RPM
|
||||
packages). This file contains a line-delimited list of JVM arguments,
|
||||
which must begin with `-`. You can add custom JVM flags to this file and
|
||||
packages). This file contains a line-delimited list of JVM arguments following
|
||||
a special syntax:
|
||||
- lines beginning with `#` are treated as comments and are ignored
|
||||
- lines consisting only of whitespace are ignored
|
||||
- lines beginning with a `-` are treated as a JVM option that applies
|
||||
independent of the version of the JVM
|
||||
- lines beginning with a number followed by a `:` followed by a `-` are treated
|
||||
as a JVM option that applies only if the version of the JVM matches the
|
||||
number
|
||||
- lines beginning with a number followed by a `-` followed by a `:` are treated
|
||||
as a JVM option that applies only if the version of the JVM is greater than
|
||||
or equal to the number
|
||||
- lines beginning with a number followed by a `-` followed by a `:` followed by
|
||||
a `-` followed by a number are treated as a JVM option that applies only if
|
||||
the version of the JVM falls in the range of the two numbers
|
||||
- all other lines are rejected
|
||||
|
||||
|
||||
You can add custom JVM flags to this file and
|
||||
check this configuration into your version control system.
|
||||
|
||||
An alternative mechanism for setting Java Virtual Machine options is
|
||||
|
|
|
@ -20,7 +20,7 @@ List projects = [
|
|||
'distribution:tar',
|
||||
'distribution:deb',
|
||||
'distribution:rpm',
|
||||
'distribution:tools:java-version-checker',
|
||||
'distribution:tools:launchers',
|
||||
'distribution:tools:plugin-cli',
|
||||
'test:framework',
|
||||
'test:fixtures:example-fixture',
|
||||
|
|
Loading…
Reference in New Issue