From a2ed88900265042ea00d534988fa21edca857e3d Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Tue, 28 Jun 2016 00:39:26 +0200 Subject: [PATCH] 8160000: Runtime.version() cause startup regressions in 9+119 Reviewed-by: mchung, psandoz, erikj, forax, iris --- jdk/make/gensrc/GensrcMisc.gmk | 6 +- .../share/classes/java/lang/Runtime.java | 179 +++++++++--------- .../java/lang/VersionProps.java.template | 55 +++++- 3 files changed, 151 insertions(+), 89 deletions(-) diff --git a/jdk/make/gensrc/GensrcMisc.gmk b/jdk/make/gensrc/GensrcMisc.gmk index 0ce43ff4f8d..475b8f1d033 100644 --- a/jdk/make/gensrc/GensrcMisc.gmk +++ b/jdk/make/gensrc/GensrcMisc.gmk @@ -34,7 +34,11 @@ $(eval $(call SetupTextFileProcessing, BUILD_VERSION_JAVA, \ @@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) diff --git a/jdk/src/java.base/share/classes/java/lang/Runtime.java b/jdk/src/java.base/share/classes/java/lang/Runtime.java index 1533130017b..fd5cb88a7d6 100644 --- a/jdk/src/java.base/share/classes/java/lang/Runtime.java +++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java @@ -27,8 +27,6 @@ package java.lang; 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.stream.Collectors; 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 class Runtime { */ 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 @@ public class Runtime { private final Optional build; private final Optional 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 - = "(?[1-9][0-9]*(?:(?:\\.0)*\\.[1-9][0-9]*)*)"; - private static final String VNUM_GROUP = "VNUM"; - - private static final String PRE = "(?:-(?
[a-zA-Z0-9]+))?";
-        private static final String PRE_GROUP   = "PRE";
-
-        private static final String 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      = "(?:-(?[-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 version string containing
-         * a version number 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 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.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 version, Optional pre,
+                Optional build, Optional optional) {
+            this.version = Collections.unmodifiableList(version);
+            this.pre = pre;
+            this.build = build;
+            this.optional = optional;
         }
 
         /**
@@ -1189,7 +1112,7 @@ public class Runtime {
          * @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 @@ public class Runtime {
         }
     }
 
+    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
+            = "(?[1-9][0-9]*(?:(?:\\.0)*\\.[1-9][0-9]*)*)";
+        private static final String VNUM_GROUP  = "VNUM";
+
+        private static final String PRE      = "(?:-(?
[a-zA-Z0-9]+))?";
+        private static final String PRE_GROUP   = "PRE";
+
+        private static final String 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      = "(?:-(?[-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 version string containing
+         * a version number 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 version = new ArrayList<>();
+            for (String i : m.group(VNUM_GROUP).split("\\."))
+                version.add(Integer.parseInt(i));
+
+            Optional pre = Optional.ofNullable(m.group(PRE_GROUP));
+
+            String b = m.group(BUILD_GROUP);
+            // $BUILD is an integer
+            Optional build = (b == null)
+                ? Optional.empty()
+                : Optional.of(Integer.parseInt(b));
+
+            Optional 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);
+        }
+    }
 }
diff --git a/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template b/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template
index dd0e038936d..c5e7b754e6d 100644
--- a/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template
+++ b/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template
@@ -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 @@ class VersionProps {
     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 @@ class VersionProps {
         System.setProperty("java.runtime.name", java_runtime_name);
     }
 
+    static List versionNumbers() {
+        List 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 pre() {
+        return optionalOf(VERSION_PRE);
+    }
+
+    static Optional build() {
+        return VERSION_BUILD.isEmpty() ?
+                Optional.empty() :
+                Optional.of(Integer.parseInt(VERSION_BUILD));
+    }
+
+    static Optional optional() {
+        return optionalOf(VERSION_OPT);
+    }
+
+    // Treat empty strings as value not being present
+    private static Optional 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 @@ class VersionProps {
                    java_vm_info + ")");
     }
 
-}
\ No newline at end of file
+}