8308960: Decouple internal Version and OperatingSystem classes

Reviewed-by: mchung
This commit is contained in:
Roger Riggs 2023-05-30 17:07:02 +00:00
parent 1b8e6bf31c
commit 323d6ceda6
5 changed files with 59 additions and 65 deletions
src/java.base
macosx/classes/jdk/internal/loader
share/classes/jdk/internal/util
test/jdk/jdk/internal/util

@ -28,14 +28,13 @@ package jdk.internal.loader;
import java.io.File;
import java.util.ArrayList;
import jdk.internal.util.OperatingSystem;
import jdk.internal.util.Version;
import jdk.internal.util.OSVersion;
class ClassLoaderHelper {
// SDK 10.15 and earlier always reports 10.16 instead of 11.x.x
private static final boolean hasDynamicLoaderCache = OperatingSystem.version()
.compareTo(new Version(10, 16)) >= 0;
private static final boolean hasDynamicLoaderCache = OSVersion.current()
.compareTo(new OSVersion(10, 16)) >= 0;
private ClassLoaderHelper() {}

@ -28,7 +28,10 @@ package jdk.internal.util;
* @param minor minor version
* @param micro micro version
*/
public record Version(int major, int minor, int micro) implements Comparable<Version> {
public record OSVersion(int major, int minor, int micro) implements Comparable<OSVersion> {
// Parse and save the current OS version
private static final OSVersion CURRENT_OSVERSION = initVersion();
/**
* {@return a Version for major, minor versions}
@ -36,17 +39,36 @@ public record Version(int major, int minor, int micro) implements Comparable<Ver
* @param major major version
* @param minor minor version
*/
public Version(int major, int minor) {
public OSVersion(int major, int minor) {
this(major, minor, 0);
}
/*
* Initialize the current Version from the os.version system property
*/
private static OSVersion initVersion() {
final String osVer = StaticProperty.osVersion();
try {
return parse(osVer);
} catch (IllegalArgumentException iae) {
throw new InternalError("os.version malformed: " + osVer, iae);
}
}
/**
* {@return the current operating system version}
*/
public static OSVersion current() {
return CURRENT_OSVERSION;
}
/**
* {@return Compare this version with another version}
*
* @param other the object to be compared
*/
@Override
public int compareTo(Version other) {
public int compareTo(OSVersion other) {
int result = Integer.compare(major, other.major);
if (result == 0) {
result = Integer.compare(minor, other.minor);
@ -76,7 +98,7 @@ public record Version(int major, int minor, int micro) implements Comparable<Ver
* @throws IllegalArgumentException if the string does not start with digits
* or digits do not follow '.'
*/
public static Version parse(String str) throws IllegalArgumentException {
public static OSVersion parse(String str) throws IllegalArgumentException {
int len = str.length();
int majorStart = 0;
int majorEnd = skipDigits(str, majorStart);
@ -94,14 +116,13 @@ public record Version(int major, int minor, int micro) implements Comparable<Ver
micro = Integer.parseInt(str.substring(microStart, microEnd));
}
}
return new Version(major, minor, micro);
return new OSVersion(major, minor, micro);
}
/**
* {@return The index of the first non-digit from start}
* @throws IllegalArgumentException if there are no digits
*/
private static int skipDigits(String s, int start) {
int index = start;
while (index < s.length() && Character.isDigit(s.charAt(index))) {

@ -22,6 +22,7 @@
*/
package jdk.internal.util;
import java.util.Locale;
import jdk.internal.util.PlatformProps;
import jdk.internal.vm.annotation.ForceInline;
@ -80,7 +81,8 @@ public enum OperatingSystem {
AIX,
;
private static final OperatingSystem CURRENT_OS = initOS(PlatformProps.CURRENT_OS_STRING);
// The current OperatingSystem
private static final OperatingSystem CURRENT_OS = initOS();
/**
* {@return {@code true} if built for the Linux operating system}
@ -126,35 +128,7 @@ public enum OperatingSystem {
* Build time names are mapped to respective uppercase enum values.
* Names not recognized throw ExceptionInInitializerError with IllegalArgumentException.
*/
private static OperatingSystem initOS(String osName) {
// Too early to use Locale conversions, manually do uppercase
StringBuilder sb = new StringBuilder(osName);
for (int i = 0; i < sb.length(); i++) {
char ch = sb.charAt(i);
if (ch >= 'a' && ch <= 'z') {
sb.setCharAt(i, (char)(ch - ('a' - 'A'))); // Map lower case down to uppercase
}
}
osName = sb.toString();
return OperatingSystem.valueOf(osName);
}
/**
* {@return the operating system version with major, minor, micro}
*/
public static Version version() {
return CURRENT_VERSION;
}
// Parse and save the current version
private static final Version CURRENT_VERSION = initVersion();
private static Version initVersion() {
final String osVer = StaticProperty.osVersion();
try {
return Version.parse(osVer);
} catch (IllegalArgumentException iae) {
throw new InternalError("os.version malformed: " + osVer, iae);
}
private static OperatingSystem initOS() {
return OperatingSystem.valueOf(PlatformProps.CURRENT_OS_STRING.toUpperCase(Locale.ROOT));
}
}

@ -33,7 +33,7 @@ import static jdk.internal.util.OperatingSystem.MACOS;
import static jdk.internal.util.OperatingSystem.WINDOWS;
import jdk.internal.util.StaticProperty;
import jdk.internal.util.Version;
import jdk.internal.util.OSVersion;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.ParameterizedTest;
@ -89,7 +89,7 @@ public class OSTest {
@Test
public void checkOsVersion() {
Version ver = OperatingSystem.version();
OSVersion ver = OSVersion.current();
String osVersion = StaticProperty.osVersion();
System.err.printf("os.version: %s, version().toString(): %s%n", osVersion, ver);
assertTrue(osVersion.startsWith(ver.toString()), "version().toString() is not prefix of vs os.version property");

@ -24,12 +24,12 @@
import java.util.stream.Stream;
import jdk.internal.util.Version;
import jdk.internal.util.OSVersion;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.fail;
@ -45,21 +45,21 @@ public class VersionTest {
private static Stream<Arguments> versionParams() {
return Stream.of(
Arguments.of("1", new Version(1, 0)),
Arguments.of("1.2", new Version(1, 2)),
Arguments.of("1.2", new Version(1, 2, 0)),
Arguments.of("1.2.3", new Version(1, 2, 3)),
Arguments.of("1-abc", new Version(1, 0, 0)), // Ignore extra
Arguments.of("1.2-abc", new Version(1, 2, 0)), // Ignore extra
Arguments.of("1.2.3.4", new Version(1, 2, 3)), // Ignore extra
Arguments.of("1.2.3-abc", new Version(1, 2, 3)) // Ignore extra
Arguments.of("1", new OSVersion(1, 0)),
Arguments.of("1.2", new OSVersion(1, 2)),
Arguments.of("1.2", new OSVersion(1, 2, 0)),
Arguments.of("1.2.3", new OSVersion(1, 2, 3)),
Arguments.of("1-abc", new OSVersion(1, 0, 0)), // Ignore extra
Arguments.of("1.2-abc", new OSVersion(1, 2, 0)), // Ignore extra
Arguments.of("1.2.3.4", new OSVersion(1, 2, 3)), // Ignore extra
Arguments.of("1.2.3-abc", new OSVersion(1, 2, 3)) // Ignore extra
);
}
@ParameterizedTest
@MethodSource("versionParams")
public void checkParse(String verName, Version expected) {
Version actual = Version.parse(verName);
public void checkParse(String verName, OSVersion expected) {
OSVersion actual = OSVersion.parse(verName);
assertEquals(actual, expected, "Parsed version mismatch");
}
@ -74,27 +74,27 @@ public class VersionTest {
@ParameterizedTest()
@MethodSource("illegalVersionParams")
public void checkIllegalParse(String verName) {
Throwable th = assertThrows(IllegalArgumentException.class, () -> Version.parse(verName));
Throwable th = assertThrows(IllegalArgumentException.class, () -> OSVersion.parse(verName));
String expectedMsg = "malformed version, missing digits: " + verName;
assertEquals(th.getMessage(), expectedMsg, "message mismatch");
}
private static Stream<Arguments> versionCompare() {
return Stream.of(
Arguments.of(new Version(2, 1), new Version(2, 1), 0),
Arguments.of(new Version(2, 1), new Version(2, 0), +1),
Arguments.of(new Version(2, 0), new Version(2, 1), -1),
Arguments.of(new Version(3, 3, 1), new Version(3, 3, 1), 0),
Arguments.of(new Version(3, 3, 1), new Version(3, 3, 0), +1),
Arguments.of(new Version(3, 3, 0), new Version(3, 3, 1), -1),
Arguments.of(new Version(2, 0), new Version(3, 0), -1),
Arguments.of(new Version(3, 0), new Version(2, 0), +1)
Arguments.of(new OSVersion(2, 1), new OSVersion(2, 1), 0),
Arguments.of(new OSVersion(2, 1), new OSVersion(2, 0), +1),
Arguments.of(new OSVersion(2, 0), new OSVersion(2, 1), -1),
Arguments.of(new OSVersion(3, 3, 1), new OSVersion(3, 3, 1), 0),
Arguments.of(new OSVersion(3, 3, 1), new OSVersion(3, 3, 0), +1),
Arguments.of(new OSVersion(3, 3, 0), new OSVersion(3, 3, 1), -1),
Arguments.of(new OSVersion(2, 0), new OSVersion(3, 0), -1),
Arguments.of(new OSVersion(3, 0), new OSVersion(2, 0), +1)
);
}
@ParameterizedTest()
@MethodSource("versionCompare")
public void checkVersionCompare(Version v1, Version v2, int expected) {
public void checkVersionCompare(OSVersion v1, OSVersion v2, int expected) {
int result1 = v1.compareTo(v2);
assertEquals(result1, expected, "v1 vs v2");
int result2 = v2.compareTo(v1);