8160000: Runtime.version() cause startup regressions in 9+119
authorredestad
Tue, 28 Jun 2016 00:39:26 +0200
changeset 39302 aa8d0bc2a6d2
parent 39301 0907704a2409
child 39303 5aefc354587e
8160000: Runtime.version() cause startup regressions in 9+119 Reviewed-by: mchung, psandoz, erikj, forax, iris
jdk/make/gensrc/GensrcMisc.gmk
jdk/src/java.base/share/classes/java/lang/Runtime.java
jdk/src/java.base/share/classes/java/lang/VersionProps.java.template
--- a/jdk/make/gensrc/GensrcMisc.gmk	Mon Jun 27 13:57:24 2016 -0700
+++ b/jdk/make/gensrc/GensrcMisc.gmk	Tue Jun 28 00:39:26 2016 +0200
@@ -34,7 +34,11 @@
         @@LAUNCHER_NAME@@ => $(LAUNCHER_NAME) ; \
         @@RUNTIME_NAME@@ => $(RUNTIME_NAME) ; \
         @@VERSION_SHORT@@ => $(VERSION_SHORT) ; \
-        @@VERSION_STRING@@ => $(VERSION_STRING), \
+        @@VERSION_STRING@@ => $(VERSION_STRING) ; \
+        @@VERSION_NUMBER@@ => $(VERSION_NUMBER) ; \
+        @@VERSION_PRE@@ => $(VERSION_PRE) ; \
+        @@VERSION_BUILD@@ => $(VERSION_BUILD) ; \
+        @@VERSION_OPT@@ => $(VERSION_OPT), \
 ))
 
 GENSRC_JAVA_BASE += $(BUILD_VERSION_JAVA)
--- a/jdk/src/java.base/share/classes/java/lang/Runtime.java	Mon Jun 27 13:57:24 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java	Tue Jun 28 00:39:26 2016 +0200
@@ -27,8 +27,6 @@
 
 import java.io.*;
 import java.math.BigInteger;
-import java.util.AbstractList;
-import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -36,11 +34,9 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
-import java.util.RandomAccess;
 import java.util.StringTokenizer;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
-import sun.security.action.GetPropertyAction;
 
 /**
  * Every Java application has a single instance of class
@@ -941,8 +937,9 @@
      */
     public static Version version() {
         if (version == null) {
-            version = Version.parse(
-                GetPropertyAction.privilegedGetProperty("java.runtime.version"));
+            version = new Version(VersionProps.versionNumbers(),
+                    VersionProps.pre(), VersionProps.build(),
+                    VersionProps.optional());
         }
         return version;
     }
@@ -1084,86 +1081,12 @@
         private final Optional<Integer> build;
         private final Optional<String>  optional;
 
-
-        // $VNUM(-$PRE)?(\+($BUILD)?(\-$OPT)?)?
-        // RE limits the format of version strings
-        // ([1-9][0-9]*(?:(?:\.0)*\.[1-9][0-9]*)*)(?:-([a-zA-Z0-9]+))?(?:(\+)(0|[1-9][0-9]*)?)?(?:-([-a-zA-Z0-9.]+))?
-
-        private static final String VNUM
-            = "(?<VNUM>[1-9][0-9]*(?:(?:\\.0)*\\.[1-9][0-9]*)*)";
-        private static final String VNUM_GROUP  = "VNUM";
-
-        private static final String PRE      = "(?:-(?<PRE>[a-zA-Z0-9]+))?";
-        private static final String PRE_GROUP   = "PRE";
-
-        private static final String BUILD
-            = "(?:(?<PLUS>\\+)(?<BUILD>0|[1-9][0-9]*)?)?";
-        private static final String PLUS_GROUP  = "PLUS";
-        private static final String BUILD_GROUP = "BUILD";
-
-        private static final String OPT      = "(?:-(?<OPT>[-a-zA-Z0-9.]+))?";
-        private static final String OPT_GROUP   = "OPT";
-
-        private static final String VSTR_FORMAT
-            = "^" + VNUM + PRE + BUILD + OPT + "$";
-        private static final Pattern VSTR_PATTERN = Pattern.compile(VSTR_FORMAT);
-
-        /**
-         * Constructs a valid <a href="verStr">version string</a> containing
-         * a <a href="#verNum">version number</a> followed by pre-release and
-         * build information.
-         *
-         * @param  s
-         *         A string to be interpreted as a version
-         *
-         * @throws  IllegalArgumentException
-         *          If the given string cannot be interpreted as a valid
-         *          version
-         *
-         * @throws  NullPointerException
-         *          If {@code s} is {@code null}
-         *
-         * @throws  NumberFormatException
-         *          If an element of the version number or the build number
-         *          cannot be represented as an {@link Integer}
-         */
-        private Version(String s) {
-            if (s == null)
-                throw new NullPointerException();
-
-            Matcher m = VSTR_PATTERN.matcher(s);
-            if (!m.matches())
-                throw new IllegalArgumentException("Invalid version string: '"
-                                                   + s + "'");
-
-            // $VNUM is a dot-separated list of integers of arbitrary length
-            List<Integer> list = new ArrayList<>();
-            for (String i : m.group(VNUM_GROUP).split("\\."))
-                list.add(Integer.parseInt(i));
-            version = Collections.unmodifiableList(list);
-
-            pre = Optional.ofNullable(m.group(PRE_GROUP));
-
-            String b = m.group(BUILD_GROUP);
-            // $BUILD is an integer
-            build = (b == null)
-                ? Optional.<Integer>empty()
-                : Optional.ofNullable(Integer.parseInt(b));
-
-            optional = Optional.ofNullable(m.group(OPT_GROUP));
-
-            // empty '+'
-            if ((m.group(PLUS_GROUP) != null) && !build.isPresent()) {
-                if (optional.isPresent()) {
-                    if (pre.isPresent())
-                        throw new IllegalArgumentException("'+' found with"
-                            + " pre-release and optional components:'" + s
-                            + "'");
-                } else {
-                    throw new IllegalArgumentException("'+' found with neither"
-                        + " build or optional components: '" + s + "'");
-                }
-            }
+        Version(List<Integer> version, Optional<String> pre,
+                Optional<Integer> build, Optional<String> optional) {
+            this.version = Collections.unmodifiableList(version);
+            this.pre = pre;
+            this.build = build;
+            this.optional = optional;
         }
 
         /**
@@ -1189,7 +1112,7 @@
          * @return  The Version of the given string
          */
         public static Version parse(String s) {
-            return new Version(s);
+            return VersionBuilder.parse(s);
         }
 
         /**
@@ -1518,4 +1441,86 @@
         }
     }
 
+    private static class VersionBuilder {
+        // $VNUM(-$PRE)?(\+($BUILD)?(\-$OPT)?)?
+        // RE limits the format of version strings
+        // ([1-9][0-9]*(?:(?:\.0)*\.[1-9][0-9]*)*)(?:-([a-zA-Z0-9]+))?(?:(\+)(0|[1-9][0-9]*)?)?(?:-([-a-zA-Z0-9.]+))?
+
+        private static final String VNUM
+            = "(?<VNUM>[1-9][0-9]*(?:(?:\\.0)*\\.[1-9][0-9]*)*)";
+        private static final String VNUM_GROUP  = "VNUM";
+
+        private static final String PRE      = "(?:-(?<PRE>[a-zA-Z0-9]+))?";
+        private static final String PRE_GROUP   = "PRE";
+
+        private static final String BUILD
+            = "(?:(?<PLUS>\\+)(?<BUILD>0|[1-9][0-9]*)?)?";
+        private static final String PLUS_GROUP  = "PLUS";
+        private static final String BUILD_GROUP = "BUILD";
+
+        private static final String OPT      = "(?:-(?<OPT>[-a-zA-Z0-9.]+))?";
+        private static final String OPT_GROUP   = "OPT";
+
+        private static final String VSTR_FORMAT
+            = "^" + VNUM + PRE + BUILD + OPT + "$";
+        private static final Pattern VSTR_PATTERN = Pattern.compile(VSTR_FORMAT);
+
+        /**
+         * Constructs a valid <a href="verStr">version string</a> containing
+         * a <a href="#verNum">version number</a> followed by pre-release and
+         * build information.
+         *
+         * @param  s
+         *         A string to be interpreted as a version
+         *
+         * @throws  IllegalArgumentException
+         *          If the given string cannot be interpreted as a valid
+         *          version
+         *
+         * @throws  NullPointerException
+         *          If {@code s} is {@code null}
+         *
+         * @throws  NumberFormatException
+         *          If an element of the version number or the build number
+         *          cannot be represented as an {@link Integer}
+         */
+        static Version parse(String s) {
+            if (s == null)
+                throw new NullPointerException();
+
+            Matcher m = VSTR_PATTERN.matcher(s);
+            if (!m.matches())
+                throw new IllegalArgumentException("Invalid version string: '"
+                                                   + s + "'");
+
+            // $VNUM is a dot-separated list of integers of arbitrary length
+            List<Integer> version = new ArrayList<>();
+            for (String i : m.group(VNUM_GROUP).split("\\."))
+                version.add(Integer.parseInt(i));
+
+            Optional<String> pre = Optional.ofNullable(m.group(PRE_GROUP));
+
+            String b = m.group(BUILD_GROUP);
+            // $BUILD is an integer
+            Optional<Integer> build = (b == null)
+                ? Optional.empty()
+                : Optional.of(Integer.parseInt(b));
+
+            Optional<String> optional = Optional.ofNullable(m.group(OPT_GROUP));
+
+            // empty '+'
+            if ((m.group(PLUS_GROUP) != null) && !build.isPresent()) {
+                if (optional.isPresent()) {
+                    if (pre.isPresent())
+                        throw new IllegalArgumentException("'+' found with"
+                            + " pre-release and optional components:'" + s
+                            + "'");
+                } else {
+                    throw new IllegalArgumentException("'+' found with neither"
+                        + " build or optional components: '" + s + "'");
+                }
+            }
+            return new Version(version, pre, build, optional);
+        }
+    }
 }
--- a/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template	Mon Jun 27 13:57:24 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template	Tue Jun 28 00:39:26 2016 +0200
@@ -26,6 +26,9 @@
 package java.lang;
 
 import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
 
 class VersionProps {
 
@@ -42,6 +45,18 @@
     private static final String java_runtime_version =
         "@@VERSION_STRING@@";
 
+    private static final String VERSION_NUMBER =
+        "@@VERSION_NUMBER@@";
+
+    private static final String VERSION_BUILD =
+        "@@VERSION_BUILD@@";
+
+    private static final String VERSION_PRE =
+        "@@VERSION_PRE@@";
+
+    private static final String VERSION_OPT =
+        "@@VERSION_OPT@@";
+
     static {
         init();
     }
@@ -52,6 +67,44 @@
         System.setProperty("java.runtime.name", java_runtime_name);
     }
 
+    static List<Integer> versionNumbers() {
+        List<Integer> versionNumbers = new ArrayList<>(4);
+        int prevIndex = 0;
+        int index = VERSION_NUMBER.indexOf('.');
+        while (index > 0) {
+            versionNumbers.add(
+                    Integer.parseInt(VERSION_NUMBER, prevIndex, index, 10));
+            prevIndex = index;
+            index = VERSION_NUMBER.indexOf('.', prevIndex);
+        }
+        versionNumbers.add(Integer.parseInt(VERSION_NUMBER,
+                prevIndex, VERSION_NUMBER.length(), 10));
+        return versionNumbers;
+    }
+
+    static Optional<String> pre() {
+        return optionalOf(VERSION_PRE);
+    }
+
+    static Optional<Integer> build() {
+        return VERSION_BUILD.isEmpty() ?
+                Optional.empty() :
+                Optional.of(Integer.parseInt(VERSION_BUILD));
+    }
+
+    static Optional<String> optional() {
+        return optionalOf(VERSION_OPT);
+    }
+
+    // Treat empty strings as value not being present
+    private static Optional<String> optionalOf(String value) {
+        if (!value.isEmpty()) {
+            return Optional.of(value);
+        } else {
+            return Optional.empty();
+        }
+    }
+
     /**
      * In case you were wondering this method is called by java -version.
      * Sad that it prints to stderr; would be nicer if default printed on
@@ -111,4 +164,4 @@
                    java_vm_info + ")");
     }
 
-}
\ No newline at end of file
+}