jvm.option是一些程序里边的java的配置参数的一个集合,不同的应用都会定义自己的jvm.options用来控制一些jvm的参数

以下,以elasticsearch为例,来说明它是如何加载的

elasticsearch的jvm.options的文件内容如下:

JVM configuration

################################################################
## IMPORTANT: JVM heap size
################################################################
##
## You should always set the min and max JVM heap
## size to the same value. For example, to set
## the heap to 4 GB, set:
##
## -Xms4g
## -Xmx4g
##
## See https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html
## for more information
##
################################################################

Xms represents the initial size of total heap space

Xmx represents the maximum size of total heap space

-Xms${heap.min}
-Xmx${heap.max}

################################################################
## Expert settings
################################################################
##
## All settings below this section are considered
## expert settings. Don't tamper with them unless
## you understand what you are doing
##
################################################################

GC configuration

-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly

optimizations

pre-touch memory pages used by the JVM during initialization

-XX:+AlwaysPreTouch

basic

explicitly set the stack size

-Xss1m

set to headless, just in case

-Djava.awt.headless=true

ensure UTF-8 encoding by default (e.g. filenames)

-Dfile.encoding=UTF-8

use our provided JNA always versus the system one

-Djna.nosys=true

turn off a JDK optimization that throws away stack traces for common

exceptions because stack traces are important for debugging

-XX:-OmitStackTraceInFastThrow

flags to configure Netty

-Dio.netty.noUnsafe=true
-Dio.netty.noKeySetOptimization=true
-Dio.netty.recycler.maxCapacityPerThread=0

log4j 2

-Dlog4j.shutdownHookEnabled=false
-Dlog4j2.disable.jmx=true

-Djava.io.tmpdir=${ES_TMPDIR}

heap dumps

generate a heap dump when an allocation from the Java heap fails

heap dumps are created in the working directory of the JVM

-XX:+HeapDumpOnOutOfMemoryError

specify an alternative path for heap dumps; ensure the directory exists and

has sufficient space

${heap.dump.path}

specify an alternative path for JVM fatal error logs

${error.file}

JDK 8 GC logging

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
# due to internationalization enhancements in JDK 9 Elasticsearch need to set the provider to COMPAT otherwise
# time/date parsing will break in an incompatible way for some date patterns and locals
9-:-Djava.locale.providers=COMPAT

temporary workaround for C2 bug with JDK 10 on hardware with AVX-512

10-:-XX:UseAVX=2

那在ES里边,是如何设置这个参数的呢

我们手动运行这个java类,会得到如下的结果:

所以,ES提供了一个JvmOptionsParser类,来解析jvm.options里设置的jvm参数,然后在应用启动的时候,把这些参数设置到应用的启动参数里边去,我们也可以参考这个思路,提供一个自己的jvm.options文件,然后写一个Parser类来解析里边的内容,然后设置到jvm的启动参数里边去

以下是ES的JvmOptionsParser类的实现

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;

import org.elasticsearch.tools.java_version_checker.JavaVersion;

/**
* 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 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()) {
List ergonomicJvmOptions = JvmErgonomics.choose(jvmOptions);
jvmOptions.addAll(ergonomicJvmOptions);
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("((?\d+)(?-)?(?\d+)?😃?(?

/**
* Parse the line-delimited JVM options from the specified buffered reader for the specified Java major version.
* Valid JVM options are:
*


    *

  • * a line starting with a dash is treated as a JVM option that applies to all versions
    *

  • *

  • * 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
    *

  • *

  • * a line starting with a number followed by a dash followed by a colon is treated as a JVM option that applies to the matching
    * Java specified major version and all larger Java major versions
    *

  • *

  • * a line starting with a number followed by a dash followed by a number followed by a colon is treated as a JVM option that
    * applies to the specified range of matching Java major versions
    *

  • *

*
* For example, if the specified Java major version is 8, the following JVM options will be accepted:
*

    *

  • * {@code -XX:+PrintGCDateStamps}
    *

  • *

  • * {@code 8:-XX:+PrintGCDateStamps}
    *

  • *

  • * {@code 8-:-XX:+PrintGCDateStamps}
    *

  • *

  • * {@code 7-8:-XX:+PrintGCDateStamps}
    *

  • *

* and the following JVM options will not be accepted:
*

    *

  • * {@code 9:-Xlog:age=trace,gc,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m}
    *

  • *

  • * {@code 9-:-Xlog:age=trace,gc,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m}
    *

  • *

  • * {@code 9-10:-Xlog:age=trace,gc,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m}
    *

  • *

*
* 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 specified 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 jvmOptions) {
final StringBuilder spaceDelimitedJvmOptionsBuilder = new StringBuilder();
final Iterator it = jvmOptions.iterator();
while (it.hasNext()) {
spaceDelimitedJvmOptionsBuilder.append(it.next());
if (it.hasNext()) {
spaceDelimitedJvmOptionsBuilder.append(" ");
}
}
return spaceDelimitedJvmOptionsBuilder.toString();
}

}

posted on 2018-11-14 10:27  梦中彩虹  阅读(6712)  评论(0)    收藏  举报