8160000: Runtime.version() cause startup regressions in 9+119
Reviewed-by: mchung, psandoz, erikj, forax, iris
--- 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
+}