# HG changeset patch # User redestad # Date 1544481413 -3600 # Mon Dec 10 23:36:53 2018 +0100 # Node ID 9afa0d67d77c2c15e53f80534d8ca05cf4238ba0 # Parent 8deeb7bba51699fe9460a41b64f2353a8f279c26 8215159: Improve initial setup of system Properties Reviewed-by: mchung, rriggs diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -801,8 +801,9 @@ } if (props == null) { - props = SystemProps.initProperties(); - VersionProps.init(props); + Map tempProps = SystemProps.initProperties(); + VersionProps.init(tempProps); + props = createProperties(tempProps); } System.props = props; } @@ -1960,17 +1961,41 @@ } /** + * Create the Properties object from a map - masking out system properties + * that are not intended for public access. + */ + private static Properties createProperties(Map initialProps) { + Properties properties = new Properties(initialProps.size()); + for (var entry : initialProps.entrySet()) { + String prop = entry.getKey(); + switch (prop) { + // Do not add private system properties to the Properties + case "sun.nio.MaxDirectMemorySize": + case "sun.nio.PageAlignDirectMemory": + // used by java.lang.Integer.IntegerCache + case "java.lang.Integer.IntegerCache.high": + // used by sun.launcher.LauncherHelper + case "sun.java.launcher.diag": + // used by jdk.internal.loader.ClassLoaders + case "jdk.boot.class.path.append": + break; + default: + properties.put(prop, entry.getValue()); + } + } + return properties; + } + + /** * Initialize the system class. Called after thread initialization. */ private static void initPhase1() { - // VM might invoke JNU_NewStringPlatform() to set those encoding // sensitive properties (user.home, user.name, boot.class.path, etc.) // during "props" initialization. // The charset is initialized in System.c and does not depend on the Properties. - props = SystemProps.initProperties(); - VersionProps.init(props); - StaticProperty.javaHome(); // Load StaticProperty to cache the property values + Map tempProps = SystemProps.initProperties(); + VersionProps.init(tempProps); // There are certain system configurations that may be controlled by // VM options such as the maximum amount of direct memory and @@ -1978,15 +2003,14 @@ // of autoboxing. Typically, the library will obtain these values // from the properties set by the VM. If the properties are for // internal implementation use only, these properties should be - // removed from the system properties. - // - // See java.lang.Integer.IntegerCache and the - // VM.saveAndRemoveProperties method for example. + // masked from the system properties. // // Save a private copy of the system properties object that - // can only be accessed by the internal implementation. Remove - // certain system properties that are not intended for public access. - VM.saveAndRemoveProperties(props); + // can only be accessed by the internal implementation. + VM.saveProperties(tempProps); + props = createProperties(tempProps); + + StaticProperty.javaHome(); // Load StaticProperty to cache the property values lineSeparator = props.getProperty("line.separator"); diff --git a/src/java.base/share/classes/java/lang/VersionProps.java.template b/src/java.base/share/classes/java/lang/VersionProps.java.template --- a/src/java.base/share/classes/java/lang/VersionProps.java.template +++ b/src/java.base/share/classes/java/lang/VersionProps.java.template @@ -28,8 +28,8 @@ import java.io.PrintStream; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Optional; -import java.util.Properties; class VersionProps { @@ -88,25 +88,25 @@ /** * Initialize system properties using build provided values. * - * @param props Properties instance in which to insert the properties + * @param props Map instance in which to insert the properties */ - public static void init(Properties props) { - props.setProperty("java.version", java_version); - props.setProperty("java.version.date", java_version_date); - props.setProperty("java.runtime.version", java_runtime_version); - props.setProperty("java.runtime.name", java_runtime_name); + public static void init(Map props) { + props.put("java.version", java_version); + props.put("java.version.date", java_version_date); + props.put("java.runtime.version", java_runtime_version); + props.put("java.runtime.name", java_runtime_name); if (VENDOR_VERSION_STRING.length() > 0) - props.setProperty("java.vendor.version", VENDOR_VERSION_STRING); + props.put("java.vendor.version", VENDOR_VERSION_STRING); - props.setProperty("java.class.version", CLASSFILE_MAJOR_MINOR); + props.put("java.class.version", CLASSFILE_MAJOR_MINOR); - props.setProperty("java.specification.version", VERSION_SPECIFICATION); - props.setProperty("java.specification.name", "Java Platform API Specification"); - props.setProperty("java.specification.vendor", "Oracle Corporation"); + props.put("java.specification.version", VERSION_SPECIFICATION); + props.put("java.specification.name", "Java Platform API Specification"); + props.put("java.specification.vendor", "Oracle Corporation"); - props.setProperty("java.vendor", VENDOR); - props.setProperty("java.vendor.url", VENDOR_URL); - props.setProperty("java.vendor.url.bug", VENDOR_URL_BUG); + props.put("java.vendor", VENDOR); + props.put("java.vendor.url", VENDOR_URL); + props.put("java.vendor.url.bug", VENDOR_URL_BUG); } private static int parseVersionNumber(String version, int prevIndex, int index) { diff --git a/src/java.base/share/classes/jdk/internal/misc/VM.java b/src/java.base/share/classes/jdk/internal/misc/VM.java --- a/src/java.base/share/classes/jdk/internal/misc/VM.java +++ b/src/java.base/share/classes/jdk/internal/misc/VM.java @@ -26,6 +26,8 @@ package jdk.internal.misc; import static java.lang.Thread.State.*; + +import java.util.Collections; import java.util.Map; import java.util.Properties; @@ -175,7 +177,7 @@ if (savedProps == null) throw new IllegalStateException("Not yet initialized"); - return savedProps; + return Collections.unmodifiableMap(savedProps); } private static Map savedProps; @@ -184,16 +186,15 @@ // the system properties that are not intended for public access. // // This method can only be invoked during system initialization. - public static void saveAndRemoveProperties(Properties props) { + public static void saveProperties(Map props) { if (initLevel() != 0) throw new IllegalStateException("Wrong init level"); - @SuppressWarnings({"rawtypes", "unchecked"}) - Map sp = - Map.ofEntries(props.entrySet().toArray(new Map.Entry[0])); // only main thread is running at this time, so savedProps and // its content will be correctly published to threads started later - savedProps = sp; + if (savedProps == null) { + savedProps = props; + } // Set the maximum amount of direct memory. This value is controlled // by the vm option -XX:MaxDirectMemorySize=. @@ -201,7 +202,7 @@ // from the system property sun.nio.MaxDirectMemorySize set by the VM. // If not set or set to -1, the max memory will be used // The system property will be removed. - String s = (String)props.remove("sun.nio.MaxDirectMemorySize"); + String s = props.get("sun.nio.MaxDirectMemorySize"); if (s == null || s.isEmpty() || s.equals("-1")) { // -XX:MaxDirectMemorySize not given, take default directMemory = Runtime.getRuntime().maxMemory(); @@ -212,19 +213,9 @@ } // Check if direct buffers should be page aligned - s = (String)props.remove("sun.nio.PageAlignDirectMemory"); + s = props.get("sun.nio.PageAlignDirectMemory"); if ("true".equals(s)) pageAlignDirectMemory = true; - - // Remove other private system properties - // used by java.lang.Integer.IntegerCache - props.remove("java.lang.Integer.IntegerCache.high"); - - // used by sun.launcher.LauncherHelper - props.remove("sun.java.launcher.diag"); - - // used by jdk.internal.loader.ClassLoaders - props.remove("jdk.boot.class.path.append"); } // Initialize any miscellaneous operating system settings that need to be diff --git a/src/java.base/share/classes/jdk/internal/util/SystemProps.java b/src/java.base/share/classes/jdk/internal/util/SystemProps.java --- a/src/java.base/share/classes/jdk/internal/util/SystemProps.java +++ b/src/java.base/share/classes/jdk/internal/util/SystemProps.java @@ -26,7 +26,9 @@ import java.lang.annotation.Native; -import java.util.Properties; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; /** * System Property initialization for internal use only @@ -47,12 +49,13 @@ * * @return a Properties instance initialized with all of the properties */ - public static Properties initProperties() { + public static Map initProperties() { + // Initially, cmdProperties only includes -D and props from the VM Raw raw = new Raw(); - Properties props = raw.cmdProperties(); + HashMap props = raw.cmdProperties(); - String javaHome = props.getProperty("java.home"); + String javaHome = props.get("java.home"); assert javaHome != null : "java.home not set"; putIfAbsent(props, "user.home", raw.propDefault(Raw._user_home_NDX)); @@ -121,7 +124,7 @@ * @param key the key * @param value the value */ - private static void put(Properties props, String key, String value) { + private static void put(HashMap props, String key, String value) { if (value != null) { props.put(key, value); } @@ -133,7 +136,7 @@ * @param key the key * @param value the value */ - private static void putIfAbsent(Properties props, String key, String value) { + private static void putIfAbsent(HashMap props, String key, String value) { if (value != null) { props.putIfAbsent(key, value); } @@ -148,10 +151,12 @@ * @param display the display value for the base * @param format the format value for the base */ - private static void fillI18nProps(Properties cmdProps, String base, String display, + private static void fillI18nProps(HashMap cmdProps, + String base, + String display, String format) { // Do not override command line setting - String baseValue = cmdProps.getProperty(base); + String baseValue = cmdProps.get(base); if (baseValue != null) { return; // Do not override value from the command line } @@ -164,7 +169,7 @@ /* user.xxx.display property */ String disp = base.concat(".display"); - String dispValue = cmdProps.getProperty(disp); + String dispValue = cmdProps.get(disp); if (dispValue == null && display != null && !display.equals(baseValue)) { // Create the property only if different from the base property cmdProps.put(disp, display); @@ -172,7 +177,7 @@ /* user.xxx.format property */ String fmt = base.concat(".format"); - String fmtValue = cmdProps.getProperty(fmt); + String fmtValue = cmdProps.get(fmt); if (fmtValue == null && format != null && !format.equals(baseValue)) { // Create the property only if different than the base property cmdProps.put(fmt, format); @@ -255,15 +260,14 @@ * * @return return a Properties instance of the command line and VM options */ - private Properties cmdProperties() { + private HashMap cmdProperties() { String[] vmProps = vmProperties(); - int nProps = vmProps.length / 2; - var cmdProps = new Properties(nProps + Raw.FIXED_LENGTH); - for (int i = 0; i < nProps; i++) { - String k = vmProps[i * 2]; + var cmdProps = new HashMap((vmProps.length / 2) + Raw.FIXED_LENGTH); + for (int i = 0; i < vmProps.length;) { + String k = vmProps[i++]; if (k != null) { - String v = vmProps[i * 2 + 1]; - cmdProps.setProperty(k, v != null ? v : ""); + String v = vmProps[i++]; + cmdProps.put(k, v != null ? v : ""); } else { // no more key/value pairs break;