--- old/src/java.base/share/classes/sun/misc/Version.java.template Tue Nov 17 14:37:55 2015 +++ new/src/java.base/share/classes/sun/misc/Version.java.template Tue Nov 17 14:37:55 2015 @@ -283,15 +283,24 @@ jvm_minor_version = Character.digit(cs.charAt(2), 10); jvm_micro_version = Character.digit(cs.charAt(4), 10); cs = cs.subSequence(5, cs.length()); - if (cs.charAt(0) == '_' && cs.length() >= 3 && - Character.isDigit(cs.charAt(1)) && - Character.isDigit(cs.charAt(2))) { - int nextChar = 3; + if (cs.charAt(0) == '_' && cs.length() >= 3) { + int nextChar = 0; + if (Character.isDigit(cs.charAt(1)) && + Character.isDigit(cs.charAt(2)) && + Character.isDigit(cs.charAt(3))) + { + nextChar = 4; + } else if (Character.isDigit(cs.charAt(1)) && + Character.isDigit(cs.charAt(2))) + { + nextChar = 3; + } + try { - String uu = cs.subSequence(1, 3).toString(); + String uu = cs.subSequence(1, nextChar).toString(); jvm_update_version = Integer.valueOf(uu).intValue(); - if (cs.length() >= 4) { - char c = cs.charAt(3); + if (cs.length() >= nextChar + 1) { + char c = cs.charAt(nextChar); if (c >= 'a' && c <= 'z') { jvm_special_version = Character.toString(c); nextChar++; --- old/src/java.base/share/native/libjava/jdk_util.c Tue Nov 17 14:37:56 2015 +++ new/src/java.base/share/native/libjava/jdk_util.c Tue Nov 17 14:37:56 2015 @@ -52,6 +52,7 @@ const char* jdk_update_string = JDK_UPDATE_VERSION; unsigned int jdk_update_version = 0; + int len_update_ver = 0; char update_ver[3]; char jdk_special_version = '\0'; @@ -78,16 +79,17 @@ assert(jdk_build_number <= 255); - if (strlen(jdk_update_string) == 2 || strlen(jdk_update_string) == 3) { - if (isdigit(jdk_update_string[0]) && isdigit(jdk_update_string[1])) { - update_ver[0] = jdk_update_string[0]; - update_ver[1] = jdk_update_string[1]; - update_ver[2] = '\0'; - jdk_update_version = (unsigned int) atoi(update_ver); - if (strlen(jdk_update_string) == 3) { - jdk_special_version = jdk_update_string[2]; - } + len_update_ver = strlen(jdk_update_string); + if (len_update_ver >= 2 && len_update_ver <= 4) { + int update_digits = len_update_ver; + + if (!isdigit(jdk_update_string[len_update_ver - 1])) { + jdk_special_version = jdk_update_string[len_update_ver -1]; + update_digits = len_update_ver - 1; } + strncpy(update_ver, jdk_update_string, update_digits); + update_ver[update_digits] = '\0'; + jdk_update_version = (unsigned int) atoi(update_ver); } memset(info, 0, info_size); --- old/test/sun/misc/Version/Version.java Tue Nov 17 14:37:57 2015 +++ new/test/sun/misc/Version/Version.java Tue Nov 17 14:37:57 2015 @@ -30,11 +30,13 @@ * @run main Version */ +import java.util.regex.*; import static sun.misc.Version.*; + public class Version { public static void main(String[] args) throws Exception { - VersionInfo jdk = newVersionInfo(System.getProperty("java.runtime.version")); + VersionInfo jdk = jdkVersionInfo(System.getProperty("java.runtime.version")); VersionInfo v1 = new VersionInfo(jdkMajorVersion(), jdkMinorVersion(), jdkMicroVersion(), @@ -45,7 +47,7 @@ if (!jdk.equals(v1)) { throw new RuntimeException("Unmatched version: " + jdk + " vs " + v1); } - VersionInfo jvm = newVersionInfo(System.getProperty("java.vm.version")); + VersionInfo jvm = jvmVersionInfo(System.getProperty("java.vm.version")); VersionInfo v2 = new VersionInfo(jvmMajorVersion(), jvmMinorVersion(), jvmMicroVersion(), @@ -96,9 +98,9 @@ } } - private static VersionInfo newVersionInfo(String version) throws Exception { + private static VersionInfo jdkVersionInfo(String version) throws Exception { // valid format of the version string is: - // n.n.n[_uu[c]][-]-bxx + // .[.][_uu[c]][-]-bxx int major = 0; int minor = 0; int micro = 0; @@ -105,65 +107,64 @@ int update = 0; String special = ""; int build = 0; - CharSequence cs = version; - if (cs.length() >= 5) { - if (Character.isDigit(cs.charAt(0)) && cs.charAt(1) == '.' && - Character.isDigit(cs.charAt(2)) && cs.charAt(3) == '.' && - Character.isDigit(cs.charAt(4))) { - major = Character.digit(cs.charAt(0), 10); - minor = Character.digit(cs.charAt(2), 10); - micro = Character.digit(cs.charAt(4), 10); - cs = cs.subSequence(5, cs.length()); - } else if (Character.isDigit(cs.charAt(0)) && - Character.isDigit(cs.charAt(1)) && cs.charAt(2) == '.' && - Character.isDigit(cs.charAt(3))) { - // HSX has nn.n[n] (major.minor) version - major = Integer.valueOf(version.substring(0, 2)).intValue(); - if (Character.isDigit(cs.charAt(4))) { - minor = Integer.valueOf(version.substring(3, 5)).intValue(); - cs = cs.subSequence(5, cs.length()); - } - else { - minor = Character.digit(cs.charAt(3), 10); - cs = cs.subSequence(4, cs.length()); - } - } - if (cs.charAt(0) == '_' && cs.length() >= 3 && - Character.isDigit(cs.charAt(1)) && - Character.isDigit(cs.charAt(2))) { - int nextChar = 3; - String uu = cs.subSequence(1, 3).toString(); - update = Integer.valueOf(uu).intValue(); - if (cs.length() >= 4) { - char c = cs.charAt(3); - if (c >= 'a' && c <= 'z') { - special = Character.toString(c); - nextChar++; - } - } - cs = cs.subSequence(nextChar, cs.length()); - } - if (cs.charAt(0) == '-') { - // skip the first character - // valid format: -bxx or bxx - // non-product VM will have -debug|-release appended - cs = cs.subSequence(1, cs.length()); - String[] res = cs.toString().split("-"); - for (int i = res.length - 1; i >= 0; i--) { - String s = res[i]; - if (s.charAt(0) == 'b') { - try { - build = Integer.parseInt(s.substring(1, s.length())); - break; - } catch (NumberFormatException nfe) { - // ignore - } - } - } - } - } + + String regex = "^([0-9]{1,2})"; // major + regex += "\\."; // separator + regex += "([0-9]{1,2})"; // minor + regex += "(\\."; // separator + regex += "([0-9]{1,2})"; // micro + regex += ")?"; // micro is optional + regex += "(_"; + regex += "([0-9]{2,3})"; // update + regex += "([a-z])?"; // special char (optional) + regex += ")?"; // _uu[c] is optional + regex += ".*"; // - + regex += "(\\-b([0-9]{1,3}$))"; // JDK -bxx + + Pattern p = Pattern.compile(regex); + Matcher m = p.matcher(version); + m.matches(); + + major = Integer.parseInt(m.group(1)); + minor = Integer.parseInt(m.group(2)); + micro = (m.group(4) == null) ? 0 : Integer.parseInt(m.group(4)); + update = (m.group(6) == null) ? 0 : Integer.parseInt(m.group(6)); + special = (m.group(7) == null) ? "" : m.group(7); + build = Integer.parseInt(m.group(9)); + VersionInfo vi = new VersionInfo(major, minor, micro, update, special, build); - System.out.printf("newVersionInfo: input=%s output=%s\n", version, vi); + System.out.printf("jdkVersionInfo: input=%s output=%s\n", version, vi); return vi; } + + private static VersionInfo jvmVersionInfo(String version) throws Exception { + try { + // valid format of the version string is: + // .-bxx[-][-] + int major = 0; + int minor = 0; + int build = 0; + + String regex = "^([0-9]{1,2})"; // major + regex += "\\."; // separator + regex += "([0-9]{1,2})"; // minor + regex += "(\\-b([0-9]{1,3}))"; // JVM -bxx + regex += ".*"; + + Pattern p = Pattern.compile(regex); + Matcher m = p.matcher(version); + m.matches(); + + major = Integer.parseInt(m.group(1)); + minor = Integer.parseInt(m.group(2)); + build = Integer.parseInt(m.group(4)); + + VersionInfo vi = new VersionInfo(major, minor, 0, 0, "", build); + System.out.printf("jvmVersionInfo: input=%s output=%s\n", version, vi); + return vi; + } catch (IllegalStateException e) { + // local builds may also follow the jdkVersionInfo format + return jdkVersionInfo(version); + } + } }