• jvm.option是什么,它是如何加载的


    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<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()) {
                List<String> 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("((?<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 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
         *     </li>
         *     <li>
         *         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
         *     </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 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<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();
        }
    
    }
  • 相关阅读:
    ehcache如何判断缓存数据是否存在--isKeyInCache
    ehcache 缓存监控
    XSS跨站脚本攻击
    java根据文件头判断文件类型
    Spring Security使用Authentication获取当前用户信息
    HttpSessionListener的用法
    ehcache缓存配置与参数说明
    [CERC2017]Buffalo Barricades
    [POI2001]Gra绿色游戏
    移动游戏By HYJ
  • 原文地址:https://www.cnblogs.com/jiaoyiping/p/9956593.html
Copyright © 2020-2023  润新知