8192833: JEP 322: Time-Based Release Versioning

Reviewed-by: erikj, ihse, iris, mchung, psandoz, tbell
This commit is contained in:
Mark Reinhold 2017-12-13 17:28:24 -08:00
parent 4be0e4c6f6
commit 0214135fde
20 changed files with 542 additions and 310 deletions

View file

@ -899,81 +899,68 @@ public class Runtime {
*
* <h2><a id="verNum">Version numbers</a></h2>
*
* <p> A <em>version number</em>, {@code $VNUM}, is a non-empty sequence
* of elements separated by period characters (U+002E). An element is
* either zero, or an unsigned integer numeral without leading zeros. The
* final element in a version number must not be zero. The format is:
* </p>
* <p> A <em>version number</em>, {@code $VNUM}, is a non-empty sequence of
* elements separated by period characters (U+002E). An element is either
* zero, or an unsigned integer numeral without leading zeros. The final
* element in a version number must not be zero. When an element is
* incremented, all subsequent elements are removed. The format is: </p>
*
* <blockquote><pre>
* [1-9][0-9]*((\.0)*\.[1-9][0-9]*)*
* [1-9][0-9]*((\.0)*\.[1-9][0-9]*)*
* </pre></blockquote>
*
* <p> The sequence may be of arbitrary length but the first three
* elements are assigned specific meanings, as follows:</p>
* <p> The sequence may be of arbitrary length but the first four elements
* are assigned specific meanings, as follows:</p>
*
* <blockquote><pre>
* $MAJOR.$MINOR.$SECURITY
* $FEATURE.$INTERIM.$UPDATE.$PATCH
* </pre></blockquote>
*
* <ul>
*
* <li><p> <a id="major">{@code $MAJOR}</a> --- The major version
* number, incremented for a major release that contains significant new
* features as specified in a new edition of the Java&#160;SE Platform
* Specification, <em>e.g.</em>, <a
* href="https://jcp.org/en/jsr/detail?id=337">JSR 337</a> for
* Java&#160;SE&#160;8. Features may be removed in a major release, given
* advance notice at least one major release ahead of time, and
* incompatible changes may be made when justified. The {@code $MAJOR}
* version number of JDK&#160;8 is {@code 8}; the {@code $MAJOR} version
* number of JDK&#160;9 is {@code 9}. When {@code $MAJOR} is incremented,
* all subsequent elements are removed. </p></li>
* <li><p> <a id="FEATURE">{@code $FEATURE}</a> &#x2014; The
* feature-release counter, incremented for every feature release
* regardless of release content. Features may be added in a feature
* release; they may also be removed, if advance notice was given at least
* one feature release ahead of time. Incompatible changes may be made
* when justified. </p></li>
*
* <li><p> <a id="minor">{@code $MINOR}</a> --- The minor version
* number, incremented for a minor update release that may contain
* compatible bug fixes, revisions to standard APIs mandated by a
* <a href="https://jcp.org/en/procedures/jcp2#5.3">Maintenance Release</a>
* of the relevant Platform Specification, and implementation features
* outside the scope of that Specification such as new JDK-specific APIs,
* additional service providers, new garbage collectors, and ports to new
* hardware architectures. </p></li>
* <li><p> <a id="INTERIM">{@code $INTERIM}</a> &#x2014; The
* interim-release counter, incremented for non-feature releases that
* contain compatible bug fixes and enhancements but no incompatible
* changes, no feature removals, and no changes to standard APIs.
* </p></li>
*
* <li><p> <a id="security">{@code $SECURITY}</a> --- The security
* level, incremented for a security update release that contains critical
* fixes including those necessary to improve security. {@code $SECURITY}
* is <strong>not</strong> reset when {@code $MINOR} is incremented. A
* higher value of {@code $SECURITY} for a given {@code $MAJOR} value,
* therefore, always indicates a more secure release, regardless of the
* value of {@code $MINOR}. </p></li>
* <li><p> <a id="UPDATE">{@code $UPDATE}</a> &#x2014; The update-release
* counter, incremented for compatible update releases that fix security
* issues, regressions, and bugs in newer features. </p></li>
*
* <li><p> <a id="PATCH">{@code $PATCH}</a> &#x2014; The emergency
* patch-release counter, incremented only when it's necessary to produce
* an emergency release to fix a critical issue. </p></li>
*
* </ul>
*
* <p> The fourth and later elements of a version number are free for use
* by downstream consumers of this code base. Such a consumer may,
* <em>e.g.</em>, use the fourth element to identify patch releases which
* contain a small number of critical non-security fixes in addition to
* the security fixes in the corresponding security release. </p>
* <p> The fifth and later elements of a version number are free for use by
* platform implementors, to identify implementor-specific patch
* releases. </p>
*
* <p> The version number does not include trailing zero elements;
* <em>i.e.</em>, {@code $SECURITY} is omitted if it has the value zero,
* and {@code $MINOR} is omitted if both {@code $MINOR} and {@code
* $SECURITY} have the value zero. </p>
* <p> A version number never has trailing zero elements. If an element
* and all those that follow it logically have the value zero then all of
* them are omitted. </p>
*
* <p> The sequence of numerals in a version number is compared to another
* such sequence in numerical, pointwise fashion; <em>e.g.</em>, {@code
* 9.9.1} is less than {@code 9.10.3}. If one sequence is shorter than
* another then the missing elements of the shorter sequence are
* considered to be less than the corresponding elements of the longer
* sequence; <em>e.g.</em>, {@code 9.1.2} is less than {@code 9.1.2.1}.
* </p>
* 10.0.4} is less than {@code 10.1.2}. If one sequence is shorter than
* another then the missing elements of the shorter sequence are considered
* to be less than the corresponding elements of the longer sequence;
* <em>e.g.</em>, {@code 10.0.2} is less than {@code 10.0.2.1}. </p>
*
* <h2><a id="verStr">Version strings</a></h2>
*
* <p> A <em>version string</em>, {@code $VSTR}, consists of a version
* number {@code $VNUM}, as described above, optionally followed by
* pre-release and build information, in one of the following formats:
* </p>
* <p> A <em>version string</em>, {@code $VSTR}, is a version number {@code
* $VNUM}, as described above, optionally followed by pre-release and build
* information, in one of the following formats: </p>
*
* <blockquote><pre>
* $VNUM(-$PRE)?\+$BUILD(-$OPT)?
@ -986,19 +973,19 @@ public class Runtime {
* <ul>
*
* <li><p> <a id="pre">{@code $PRE}</a>, matching {@code ([a-zA-Z0-9]+)}
* --- A pre-release identifier. Typically {@code ea}, for a
* potentially unstable early-access release under active development,
* or {@code internal}, for an internal developer build. </p></li>
* &#x2014; A pre-release identifier. Typically {@code ea}, for a
* potentially unstable early-access release under active development, or
* {@code internal}, for an internal developer build. </p></li>
*
* <li><p> <a id="build">{@code $BUILD}</a>, matching {@code
* (0|[1-9][0-9]*)} --- The build number, incremented for each promoted
* (0|[1-9][0-9]*)} &#x2014; The build number, incremented for each promoted
* build. {@code $BUILD} is reset to {@code 1} when any portion of {@code
* $VNUM} is incremented. </p></li>
*
* <li><p> <a id="opt">{@code $OPT}</a>, matching {@code
* ([-a-zA-Z0-9.]+)} --- Additional build information, if desired. In
* the case of an {@code internal} build this will often contain the date
* and time of the build. </p></li>
* <li><p> <a id="opt">{@code $OPT}</a>, matching {@code ([-a-zA-Z0-9.]+)}
* &#x2014; Additional build information, if desired. In the case of an
* {@code internal} build this will often contain the date and time of the
* build. </p></li>
*
* </ul>
*
@ -1082,7 +1069,7 @@ public class Runtime {
throw new NullPointerException();
// Shortcut to avoid initializing VersionPattern when creating
// major version constants during startup
// feature-version constants during startup
if (isSimpleNumber(s)) {
return new Version(List.of(Integer.parseInt(s)),
Optional.empty(), Optional.empty(), Optional.empty());
@ -1139,43 +1126,114 @@ public class Runtime {
}
/**
* Returns the <a href="#major">major</a> version number.
* Returns the value of the <a href="#FEATURE">feature</a> element of
* the version number.
*
* @return The major version number
* @return The value of the feature element
*
* @since 10
*/
public int major() {
public int feature() {
return version.get(0);
}
/**
* Returns the <a href="#minor">minor</a> version number or zero if it
* was not set.
* Returns the value of the <a href="#INTERIM">interim</a> element of
* the version number, or zero if it is absent.
*
* @return The minor version number or zero if it was not set
* @return The value of the interim element, or zero
*
* @since 10
*/
public int minor() {
public int interim() {
return (version.size() > 1 ? version.get(1) : 0);
}
/**
* Returns the <a href="#security">security</a> version number or zero
* if it was not set.
* Returns the value of the <a href="#UPDATE">update</a> element of the
* version number, or zero if it is absent.
*
* @return The security version number or zero if it was not set
* @return The value of the update element, or zero
*
* @since 10
*/
public int security() {
public int update() {
return (version.size() > 2 ? version.get(2) : 0);
}
/**
* Returns an unmodifiable {@link java.util.List List} of the
* integer numerals contained in the <a href="#verNum">version
* number</a>. The {@code List} always contains at least one
* element corresponding to the <a href="#major">major version
* number</a>.
* Returns the value of the <a href="#PATCH">patch</a> element of the
* version number, or zero if it is absent.
*
* @return An unmodifiable list of the integer numerals
* contained in the version number
* @return The value of the patch element, or zero
*
* @since 10
*/
public int patch() {
return (version.size() > 3 ? version.get(3) : 0);
}
/**
* Returns the value of the major element of the version number.
*
* @deprecated As of Java&nbsp;SE 10, the first element of a version
* number is not the major-release number but the feature-release
* counter, incremented for every time-based release. Use the {@link
* #feature()} method in preference to this method. For compatibility,
* this method returns the value of the <a href="FEATURE">feature</a>
* element.
*
* @return The value of the feature element
*/
@Deprecated(since = "10")
public int major() {
return feature();
}
/**
* Returns the value of the minor element of the version number, or
* zero if it is absent.
*
* @deprecated As of Java&nbsp;SE 10, the second element of a version
* number is not the minor-release number but the interim-release
* counter, incremented for every interim release. Use the {@link
* #interim()} method in preference to this method. For compatibility,
* this method returns the value of the <a href="INTERIM">interim</a>
* element, or zero if it is absent.
*
* @return The value of the interim element, or zero
*/
@Deprecated(since = "10")
public int minor() {
return interim();
}
/**
* Returns the value of the security element of the version number, or
* zero if it is absent.
*
* @deprecated As of Java&nbsp;SE 10, the third element of a version
* number is not the security level but the update-release counter,
* incremented for every update release. Use the {@link #update()}
* method in preference to this method. For compatibility, this method
* returns the value of the <a href="UPDATE">update</a> element, or
* zero if it is absent.
*
* @return The value of the update element, or zero
*/
@Deprecated(since = "10")
public int security() {
return update();
}
/**
* Returns an unmodifiable {@link java.util.List List} of the integers
* represented in the <a href="#verNum">version number</a>. The {@code
* List} always contains at least one element corresponding to the <a
* href="#feature">feature version number</a>.
*
* @return An unmodifiable list of the integers
* represented in the version number
*/
public List<Integer> version() {
return version;

View file

@ -550,8 +550,10 @@ public final class System {
* System properties. The following properties are guaranteed to be defined:
* <dl>
* <dt>java.version <dd>Java version number
* <dt>java.version.date <dd>Java version date
* <dt>java.vendor <dd>Java vendor specific string
* <dt>java.vendor.url <dd>Java vendor URL
* <dt>java.vendor.version <dd>Java vendor version
* <dt>java.home <dd>Java installation directory
* <dt>java.class.version <dd>Java class version number
* <dt>java.class.path <dd>Java classpath
@ -591,12 +593,18 @@ public final class System {
* </thead>
* <tbody>
* <tr><th scope="row"><code>java.version</code></th>
* <td>Java Runtime Environment version which may be interpreted
* <td>Java Runtime Environment version, which may be interpreted
* as a {@link Runtime.Version}</td></tr>
* <tr><th scope="row"><code>java.version.date</code></th>
* <td>Java Runtime Environment version date, in ISO-8601 YYYY-MM-DD
* format, which may be interpreted as a {@link
* java.time.LocalDate}</td></tr>
* <tr><th scope="row"><code>java.vendor</code></th>
* <td>Java Runtime Environment vendor</td></tr>
* <tr><th scope="row"><code>java.vendor.url</code></th>
* <td>Java vendor URL</td></tr>
* <tr><th scope="row"><code>java.vendor.version</code></th>
* <td>Java vendor version</td></tr>
* <tr><th scope="row"><code>java.home</code></th>
* <td>Java installation directory</td></tr>
* <tr><th scope="row"><code>java.vm.specification.version</code></th>

View file

@ -32,13 +32,15 @@ import java.util.Optional;
class VersionProps {
private static final String launcher_name =
"@@LAUNCHER_NAME@@";
private static final String java_version =
"@@VERSION_SHORT@@";
private static final String java_version_date =
"@@VERSION_DATE@@";
private static final String java_runtime_name =
"@@RUNTIME_NAME@@";
@ -57,14 +59,27 @@ class VersionProps {
private static final String VERSION_OPT =
"@@VERSION_OPT@@";
private static final boolean isLTS =
"@@VERSION_OPT@@".startsWith("LTS");
private static final String VENDOR_VERSION_STRING =
"@@VENDOR_VERSION_STRING@@";
private static final String vendor_version =
(VENDOR_VERSION_STRING.length() > 0
? " " + VENDOR_VERSION_STRING : "");
static {
init();
}
public static void init() {
System.setProperty("java.version", java_version);
System.setProperty("java.version.date", java_version_date);
System.setProperty("java.runtime.version", java_runtime_version);
System.setProperty("java.runtime.name", java_runtime_name);
if (VENDOR_VERSION_STRING.length() > 0)
System.setProperty("java.vendor.version", VENDOR_VERSION_STRING);
}
private static int parseVersionNumber(String version, int prevIndex, int index) {
@ -162,31 +177,36 @@ class VersionProps {
/* First line: platform version. */
if (err) {
ps.println(launcher_name + " version \"" + java_version + "\"");
ps.println(launcher_name + " version \"" + java_version + "\""
+ " " + java_version_date
+ (isLTS ? " LTS" : ""));
} else {
/* Use a format more in line with GNU conventions */
ps.println(launcher_name + " " + java_version);
ps.println(launcher_name + " " + java_version
+ " " + java_version_date
+ (isLTS ? " LTS" : ""));
}
/* Second line: runtime version (ie, libraries). */
String jdk_debug_level = System.getProperty("jdk.debug", "release");
/* Debug level is not printed for "release" builds */
if ("release".equals(jdk_debug_level)) {
/* Do not show debug level "release" builds */
jdk_debug_level = "";
} else {
jdk_debug_level = jdk_debug_level + " ";
}
ps.print(java_runtime_name + " (" + jdk_debug_level + "build " + java_runtime_version);
ps.println(')');
ps.println(java_runtime_name + vendor_version
+ " (" + jdk_debug_level + "build " + java_runtime_version + ")");
/* Third line: JVM information. */
String java_vm_name = System.getProperty("java.vm.name");
String java_vm_version = System.getProperty("java.vm.version");
String java_vm_info = System.getProperty("java.vm.info");
ps.println(java_vm_name + " (" + jdk_debug_level + "build " + java_vm_version + ", " +
java_vm_info + ")");
ps.println(java_vm_name + vendor_version
+ " (" + jdk_debug_level + "build " + java_vm_version + ", "
+ java_vm_info + ")");
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -112,9 +112,9 @@ import java.util.zip.ZipFile;
* <li>
* {@code jdk.util.jar.version} can be assigned a value that is the
* {@code String} representation of a non-negative integer
* {@code <= Runtime.version().major()}. The value is used to set the effective
* {@code <= Runtime.version().feature()}. The value is used to set the effective
* runtime version to something other than the default value obtained by
* evaluating {@code Runtime.version().major()}. The effective runtime version
* evaluating {@code Runtime.version().feature()}. The effective runtime version
* is the version that the {@link JarFile#JarFile(File, boolean, int, Runtime.Version)}
* constructor uses when the value of the last argument is
* {@code JarFile.runtimeVersion()}.
@ -143,7 +143,7 @@ import java.util.zip.ZipFile;
public
class JarFile extends ZipFile {
private final static Runtime.Version BASE_VERSION;
private final static int BASE_VERSION_MAJOR;
private final static int BASE_VERSION_FEATURE;
private final static Runtime.Version RUNTIME_VERSION;
private final static boolean MULTI_RELEASE_ENABLED;
private final static boolean MULTI_RELEASE_FORCED;
@ -153,7 +153,7 @@ class JarFile extends ZipFile {
private boolean jvInitialized;
private boolean verify;
private final Runtime.Version version; // current version
private final int versionMajor; // version.major()
private final int versionFeature; // version.feature()
private boolean isMultiRelease; // is jar multi-release?
// indicates if Class-Path attribute present
@ -170,14 +170,14 @@ class JarFile extends ZipFile {
JUZFA = jdk.internal.misc.SharedSecrets.getJavaUtilZipFileAccess();
// multi-release jar file versions >= 9
BASE_VERSION = Runtime.Version.parse(Integer.toString(8));
BASE_VERSION_MAJOR = BASE_VERSION.major();
BASE_VERSION_FEATURE = BASE_VERSION.feature();
String jarVersion = GetPropertyAction.privilegedGetProperty("jdk.util.jar.version");
int runtimeVersion = Runtime.version().major();
int runtimeVersion = Runtime.version().feature();
if (jarVersion != null) {
int jarVer = Integer.parseInt(jarVersion);
runtimeVersion = (jarVer > runtimeVersion)
? runtimeVersion
: Math.max(jarVer, BASE_VERSION_MAJOR);
: Math.max(jarVer, BASE_VERSION_FEATURE);
}
RUNTIME_VERSION = Runtime.Version.parse(Integer.toString(runtimeVersion));
String enableMultiRelease = GetPropertyAction
@ -224,10 +224,10 @@ class JarFile extends ZipFile {
* Returns the version that represents the effective runtime versioned
* configuration of a multi-release jar file.
* <p>
* By default the major version number of the returned {@code Version} will
* be equal to the major version number of {@code Runtime.version()}.
* By default the feature version number of the returned {@code Version} will
* be equal to the feature version number of {@code Runtime.version()}.
* However, if the {@code jdk.util.jar.version} property is set, the
* returned {@code Version} is derived from that property and major version
* returned {@code Version} is derived from that property and feature version
* numbers may not be equal.
*
* @return the version that represents the runtime versioned configuration
@ -322,7 +322,7 @@ class JarFile extends ZipFile {
* <p>
* The canonical form derived from the version parameter is
* {@code Runtime.Version.parse(Integer.toString(n))} where {@code n} is
* {@code Math.max(version.major(), JarFile.baseVersion().major())}.
* {@code Math.max(version.feature(), JarFile.baseVersion().feature())}.
*
* @param file the jar file to be opened for reading
* @param verify whether or not to verify the jar file if
@ -341,17 +341,17 @@ class JarFile extends ZipFile {
super(file, mode);
this.verify = verify;
Objects.requireNonNull(version);
if (MULTI_RELEASE_FORCED || version.major() == RUNTIME_VERSION.major()) {
if (MULTI_RELEASE_FORCED || version.feature() == RUNTIME_VERSION.feature()) {
// This deals with the common case where the value from JarFile.runtimeVersion() is passed
this.version = RUNTIME_VERSION;
} else if (version.major() <= BASE_VERSION_MAJOR) {
} else if (version.feature() <= BASE_VERSION_FEATURE) {
// This also deals with the common case where the value from JarFile.baseVersion() is passed
this.version = BASE_VERSION;
} else {
// Canonicalize
this.version = Runtime.Version.parse(Integer.toString(version.major()));
this.version = Runtime.Version.parse(Integer.toString(version.feature()));
}
this.versionMajor = this.version.major();
this.versionFeature = this.version.feature();
}
/**
@ -579,7 +579,7 @@ class JarFile extends ZipFile {
// filter out dir META-INF/versions/ and META-INF/versions/*/
// and any entry with version > 'version'
if (index == -1 || index == (name.length() - 1) ||
Integer.parseInt(name, off, index, 10) > versionMajor) {
Integer.parseInt(name, off, index, 10) > versionFeature) {
return null;
}
} catch (NumberFormatException x) {
@ -592,11 +592,11 @@ class JarFile extends ZipFile {
}
private JarEntry getVersionedEntry(String name, JarEntry je) {
if (BASE_VERSION_MAJOR < versionMajor) {
if (BASE_VERSION_FEATURE < versionFeature) {
if (!name.startsWith(META_INF)) {
// search for versioned entry
int v = versionMajor;
while (v > BASE_VERSION_MAJOR) {
int v = versionFeature;
while (v > BASE_VERSION_FEATURE) {
JarFileEntry vje = getEntry0(META_INF_VERSIONS + v + "/" + name);
if (vje != null) {
return vje.withBasename(name);
@ -673,7 +673,7 @@ class JarFile extends ZipFile {
}
JarFileEntry realEntry() {
if (isMultiRelease() && versionMajor != BASE_VERSION_MAJOR) {
if (isMultiRelease() && versionFeature != BASE_VERSION_FEATURE) {
String entryName = super.getName();
return entryName == basename || entryName.equals(basename) ?
this : new JarFileEntry(entryName, this);