--- old/make/autoconf/jdk-version.m4 2018-11-19 18:30:38.072393425 -0500 +++ new/make/autoconf/jdk-version.m4 2018-11-19 18:30:37.908392611 -0500 @@ -91,7 +91,9 @@ AC_MSG_ERROR([--with-vendor-url must have a value]) elif [ ! [[ $with_vendor_url =~ ^[[:print:]]*$ ]] ]; then AC_MSG_ERROR([--with-vendor-url contains non-printing characters: $with_vendor_url]) - else + elif test "x$with_vendor_url" != x; then + # Only set VENDOR_URL if '--with-vendor-url' was used and is not empty. + # Otherwise we will use the value from "version-numbers" included above. VENDOR_URL="$with_vendor_url" fi AC_SUBST(VENDOR_URL) @@ -103,7 +105,9 @@ AC_MSG_ERROR([--with-vendor-bug-url must have a value]) elif [ ! [[ $with_vendor_bug_url =~ ^[[:print:]]*$ ]] ]; then AC_MSG_ERROR([--with-vendor-bug-url contains non-printing characters: $with_vendor_bug_url]) - else + elif test "x$with_vendor_bug_url" != x; then + # Only set VENDOR_URL_BUG if '--with-vendor-bug-url' was used and is not empty. + # Otherwise we will use the value from "version-numbers" included above. VENDOR_URL_BUG="$with_vendor_bug_url" fi AC_SUBST(VENDOR_URL_BUG) --- old/make/autoconf/spec.gmk.in 2018-11-19 18:30:38.832397193 -0500 +++ new/make/autoconf/spec.gmk.in 2018-11-19 18:30:38.672396400 -0500 @@ -228,7 +228,8 @@ # Only export "VENDOR" to the build if COMPANY_NAME contains a real value. # Otherwise the default value for VENDOR, which is used to set the "java.vendor" # and "java.vm.vendor" properties is hard-coded into the source code (i.e. in - # System.c in the jdk for "vm.vendor" and vm_version.cpp in the VM for "java.vm.vendor") + # VersionProps.java.template in the jdk for "vm.vendor" and + # vm_version.cpp in the VM for "java.vm.vendor") ifneq ($(COMPANY_NAME), N/A) VERSION_CFLAGS += -DVENDOR='"$(COMPANY_NAME)"' endif --- old/make/autoconf/version-numbers 2018-11-19 18:30:39.592400962 -0500 +++ new/make/autoconf/version-numbers 2018-11-19 18:30:39.432400169 -0500 @@ -43,6 +43,7 @@ JDK_RC_PLATFORM_NAME=Platform COMPANY_NAME=N/A HOTSPOT_VM_DISTRO="OpenJDK" +VENDOR_URL_BUG=http://bugreport.java.com/bugreport/ # Might need better names for these MACOSX_BUNDLE_NAME_BASE="OpenJDK" --- old/make/gensrc/GensrcMisc.gmk 2018-11-19 18:30:40.332404631 -0500 +++ new/make/gensrc/GensrcMisc.gmk 2018-11-19 18:30:40.168403818 -0500 @@ -40,7 +40,12 @@ @@VERSION_BUILD@@ => $(VERSION_BUILD) ; \ @@VERSION_OPT@@ => $(VERSION_OPT) ; \ @@VERSION_DATE@@ => $(VERSION_DATE) ; \ - @@VENDOR_VERSION_STRING@@ => $(VENDOR_VERSION_STRING), \ + @@VERSION_CLASSFILE_MAJOR@@ => $(VERSION_CLASSFILE_MAJOR) ; \ + @@VERSION_CLASSFILE_MINOR@@ => $(VERSION_CLASSFILE_MINOR) ; \ + @@VENDOR_VERSION_STRING@@ => $(VENDOR_VERSION_STRING) ; \ + @@VENDOR@@ => $(COMPANY_NAME) ; \ + @@VENDOR_URL@@ => $(VENDOR_URL) ; \ + @@VENDOR_URL_BUG@@ => $(VENDOR_URL_BUG), \ )) GENSRC_JAVA_BASE += $(BUILD_VERSION_JAVA) --- old/make/hotspot/symbols/symbols-unix 2018-11-19 18:30:41.092408400 -0500 +++ new/make/hotspot/symbols/symbols-unix 2018-11-19 18:30:40.932407607 -0500 @@ -121,6 +121,7 @@ JVM_GetNestHost JVM_GetNestMembers JVM_GetPrimitiveArrayElement +JVM_GetProperties JVM_GetProtectionDomain JVM_GetSimpleBinaryName JVM_GetStackAccessControlContext @@ -132,7 +133,6 @@ JVM_HasReferencePendingList JVM_HoldsLock JVM_IHashCode -JVM_InitProperties JVM_InitStackTraceElement JVM_InitStackTraceElementArray JVM_InitializeFromArchive --- old/make/lib/CoreLibraries.gmk 2018-11-19 18:30:41.844412129 -0500 +++ new/make/lib/CoreLibraries.gmk 2018-11-19 18:30:41.680411316 -0500 @@ -102,7 +102,6 @@ OPTIMIZATION := HIGH, \ CFLAGS := $(CFLAGS_JDKLIB) \ $(LIBJAVA_CFLAGS), \ - System.c_CFLAGS := $(VERSION_CFLAGS), \ jdk_util.c_CFLAGS := $(VERSION_CFLAGS), \ EXTRA_HEADER_DIRS := libfdlibm, \ WARNINGS_AS_ERRORS_xlc := false, \ --- old/src/hotspot/share/include/jvm.h 2018-11-19 18:30:42.604415898 -0500 +++ new/src/hotspot/share/include/jvm.h 2018-11-19 18:30:42.440415085 -0500 @@ -111,9 +111,11 @@ JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length); -JNIEXPORT jobject JNICALL -JVM_InitProperties(JNIEnv *env, jobject p); - +/* + * Return an array of all properties as alternating name and value pairs. + */ +JNIEXPORT jobjectArray JNICALL +JVM_GetProperties(JNIEnv *env); /* * java.lang.Runtime --- old/src/hotspot/share/prims/jvm.cpp 2018-11-19 18:30:43.372419706 -0500 +++ new/src/hotspot/share/prims/jvm.cpp 2018-11-19 18:30:43.204418873 -0500 @@ -354,19 +354,37 @@ #define PUTPROP(props, name, value) set_property((props), (name), (value), CHECK_(properties)); - -JVM_ENTRY(jobject, JVM_InitProperties(JNIEnv *env, jobject properties)) - JVMWrapper("JVM_InitProperties"); - ResourceMark rm; - - Handle props(THREAD, JNIHandles::resolve_non_null(properties)); - - // System property list includes both user set via -D option and - // jvm system specific properties. - for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { - if (strcmp(p->key(), "sun.nio.MaxDirectMemorySize") == 0) // Can not be defined with -D - continue; - PUTPROP(props, p->key(), p->value()); +/* + * Return all of the system properties in a Java String array with alternating + * names and values from the jvm SystemProperty. + * Which includes some internal and all commandline -D defined properties. + */ +JVM_ENTRY(jobjectArray, JVM_GetProperties(JNIEnv *env)) + JVMWrapper("JVM_GetProperties"); + ResourceMark rm(THREAD); + HandleMark hm(THREAD); + int ndx = 0; + int fixedCount = 2; + + SystemProperty* p = Arguments::system_properties(); + int count = Arguments::PropertyList_count(p); + + // Allocate result String array + InstanceKlass* ik = SystemDictionary::String_klass(); + objArrayOop r = oopFactory::new_objArray(ik, (count + fixedCount) * 2, CHECK_NULL); + objArrayHandle result_h(THREAD, r); + + while (p != NULL) { + const char * key = p->key(); + if (strcmp(key, "sun.nio.MaxDirectMemorySize") != 0) { + const char * value = p->value(); + Handle key_str = java_lang_String::create_from_platform_dependent_str(key, CHECK_NULL); + Handle value_str = java_lang_String::create_from_platform_dependent_str((value != NULL ? value : ""), CHECK_NULL); + result_h->obj_at_put(ndx * 2, key_str()); + result_h->obj_at_put(ndx * 2 + 1, value_str()); + ndx++; + } + p = p->next(); } // Convert the -XX:MaxDirectMemorySize= command line flag @@ -377,7 +395,11 @@ if (!FLAG_IS_DEFAULT(MaxDirectMemorySize)) { char as_chars[256]; jio_snprintf(as_chars, sizeof(as_chars), JULONG_FORMAT, MaxDirectMemorySize); - PUTPROP(props, "sun.nio.MaxDirectMemorySize", as_chars); + Handle key_str = java_lang_String::create_from_platform_dependent_str("sun.nio.MaxDirectMemorySize", CHECK_NULL); + Handle value_str = java_lang_String::create_from_platform_dependent_str(as_chars, CHECK_NULL); + result_h->obj_at_put(ndx * 2, key_str()); + result_h->obj_at_put(ndx * 2 + 1, value_str()); + ndx++; } // JVM monitoring and management support @@ -406,11 +428,15 @@ if (*compiler_name != '\0' && (Arguments::mode() != Arguments::_int)) { - PUTPROP(props, "sun.management.compiler", compiler_name); + Handle key_str = java_lang_String::create_from_platform_dependent_str("sun.management.compiler", CHECK_NULL); + Handle value_str = java_lang_String::create_from_platform_dependent_str(compiler_name, CHECK_NULL); + result_h->obj_at_put(ndx * 2, key_str()); + result_h->obj_at_put(ndx * 2 + 1, value_str()); + ndx++; } } - return properties; + return (jobjectArray) JNIHandles::make_local(env, result_h()); JVM_END --- old/src/java.base/share/classes/java/lang/System.java 2018-11-19 18:30:44.168423653 -0500 +++ new/src/java.base/share/classes/java/lang/System.java 2018-11-19 18:30:44.000422820 -0500 @@ -72,6 +72,7 @@ import jdk.internal.logger.LoggerFinderLoader; import jdk.internal.logger.LazyLoggers; import jdk.internal.logger.LocalizedLoggerWrapper; +import jdk.internal.util.SystemProps; import jdk.internal.vm.annotation.Stable; import sun.reflect.annotation.AnnotationType; import sun.nio.ch.Interruptible; @@ -605,7 +606,6 @@ */ private static Properties props; - private static native Properties initProperties(Properties props); /** * Determines the current system properties. @@ -799,9 +799,9 @@ if (sm != null) { sm.checkPropertiesAccess(); } + if (props == null) { - props = new Properties(); - initProperties(props); + props = SystemProps.initProperties(); VersionProps.init(props); } System.props = props; @@ -1966,14 +1966,9 @@ // VM might invoke JNU_NewStringPlatform() to set those encoding // sensitive properties (user.home, user.name, boot.class.path, etc.) - // during "props" initialization, in which it may need access, via - // System.getProperty(), to the related system encoding property that - // have been initialized (put into "props") at early stage of the - // initialization. So make sure the "props" is available at the - // very beginning of the initialization and all system properties to - // be put into it directly. - props = new Properties(84); - initProperties(props); // initialized by the VM + // during "props" initialization. + // The charset is initialized in System.c and does not depend on the Properties. + props = SystemProps.initProperties(); VersionProps.init(props); // There are certain system configurations that may be controlled by @@ -1993,7 +1988,6 @@ VM.saveAndRemoveProperties(props); lineSeparator = props.getProperty("line.separator"); - StaticProperty.javaHome(); // Load StaticProperty to cache the property values FileInputStream fdIn = new FileInputStream(FileDescriptor.in); FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); --- old/src/java.base/share/classes/java/lang/VersionProps.java.template 2018-11-19 18:30:44.964427600 -0500 +++ new/src/java.base/share/classes/java/lang/VersionProps.java.template 2018-11-19 18:30:44.800426787 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2018, 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 @@ -63,6 +63,9 @@ private static final boolean isLTS = "@@VERSION_OPT@@".startsWith("LTS"); + private static final String CLASSFILE_MAJOR_MINOR = + "@@VERSION_CLASSFILE_MAJOR@@.@@VERSION_CLASSFILE_MINOR@@"; + private static final String VENDOR_VERSION_STRING = "@@VENDOR_VERSION_STRING@@"; @@ -70,6 +73,20 @@ (VENDOR_VERSION_STRING.length() > 0 ? " " + VENDOR_VERSION_STRING : ""); + private static final String VENDOR = + "@@VENDOR@@"; + + private static final String VENDOR_URL = + "@@VENDOR_URL@@"; + + private static final String VENDOR_URL_BUG = + "@@VENDOR_URL_BUG@@"; + + /** + * Initialize system properties using build provided values. + * + * @param props Properties 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); @@ -77,6 +94,22 @@ props.setProperty("java.runtime.name", java_runtime_name); if (VENDOR_VERSION_STRING.length() > 0) props.setProperty("java.vendor.version", VENDOR_VERSION_STRING); + + props.setProperty("java.class.version", CLASSFILE_MAJOR_MINOR); + + props.setProperty("java.specification.version", VERSION_NUMBER); + props.setProperty("java.specification.name", "Java Platform API Specification"); + props.setProperty("java.specification.vendor", "Oracle Corporation"); + + if (!VENDOR.isEmpty()) { + props.setProperty("java.vendor", VENDOR); + } + if (!VENDOR_URL.isEmpty()) { + props.setProperty("java.vendor.url", VENDOR_URL); + } + if (!VENDOR_URL_BUG.isEmpty()) { + props.setProperty("java.vendor.url.bug", VENDOR_URL_BUG); + } } private static int parseVersionNumber(String version, int prevIndex, int index) { --- old/src/java.base/share/native/libjava/System.c 2018-11-19 18:30:45.736431429 -0500 +++ new/src/java.base/share/native/libjava/System.c 2018-11-19 18:30:45.568430596 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2018, 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 @@ -31,6 +31,7 @@ #include "java_props.h" #include "java_lang_System.h" +#include "jdk_internal_util_SystemProps_Raw.h" #define OBJ "Ljava/lang/Object;" @@ -56,255 +57,163 @@ return JVM_IHashCode(env, x); } -#define PUTPROP(props, key, val) \ - if (1) { \ - jstring jkey, jval; \ - jobject r; \ - jkey = (*env)->NewStringUTF(env, key); \ - if (jkey == NULL) return NULL; \ - jval = (*env)->NewStringUTF(env, val); \ - if (jval == NULL) return NULL; \ - r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \ - if ((*env)->ExceptionOccurred(env)) return NULL; \ - (*env)->DeleteLocalRef(env, jkey); \ - (*env)->DeleteLocalRef(env, jval); \ - (*env)->DeleteLocalRef(env, r); \ - } else ((void) 0) - -/* "key" is a char type string with only ASCII character in it. - "val" is a nchar (typedefed in java_props.h) type string */ - -#define PUTPROP_ForPlatformNString(props, key, val) \ - if (1) { \ - jstring jkey, jval; \ - jobject r; \ - jkey = (*env)->NewStringUTF(env, key); \ - if (jkey == NULL) return NULL; \ - jval = GetStringPlatform(env, val); \ - if (jval == NULL) return NULL; \ - r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \ - if ((*env)->ExceptionOccurred(env)) return NULL; \ - (*env)->DeleteLocalRef(env, jkey); \ - (*env)->DeleteLocalRef(env, jval); \ - (*env)->DeleteLocalRef(env, r); \ - } else ((void) 0) -#define REMOVEPROP(props, key) \ - if (1) { \ - jstring jkey; \ - jobject r; \ - jkey = JNU_NewStringPlatform(env, key); \ - if (jkey == NULL) return NULL; \ - r = (*env)->CallObjectMethod(env, props, removeID, jkey); \ - if ((*env)->ExceptionOccurred(env)) return NULL; \ - (*env)->DeleteLocalRef(env, jkey); \ - (*env)->DeleteLocalRef(env, r); \ - } else ((void) 0) -#define GETPROP(props, key, jret) \ - if (1) { \ - jstring jkey = JNU_NewStringPlatform(env, key); \ - if (jkey == NULL) return NULL; \ - jret = (*env)->CallObjectMethod(env, props, getPropID, jkey); \ - if ((*env)->ExceptionOccurred(env)) return NULL; \ - (*env)->DeleteLocalRef(env, jkey); \ - } else ((void) 0) - -/* Third party may overwrite these values. */ -#ifndef VENDOR -#define VENDOR "Oracle Corporation" -#endif -#ifndef VENDOR_URL -#define VENDOR_URL "http://java.oracle.com/" -#endif -#ifndef VENDOR_URL_BUG -#define VENDOR_URL_BUG "http://bugreport.java.com/bugreport/" -#endif - -#ifdef JAVA_SPECIFICATION_VENDOR /* Third party may NOT overwrite this. */ - #error "ERROR: No override of JAVA_SPECIFICATION_VENDOR is allowed" -#else - #define JAVA_SPECIFICATION_VENDOR "Oracle Corporation" -#endif +/* VENDOR, VENDOR_URL, VENDOR_URL_BUG are set in VersionProps.java.template. */ -jobject fillI18nProps(JNIEnv *env, jobject props, char *baseKey, - char *platformDispVal, char *platformFmtVal, - jmethodID putID, jmethodID getPropID) { - jstring jVMBaseVal = NULL; - - GETPROP(props, baseKey, jVMBaseVal); - if (jVMBaseVal) { - // user specified the base property. there's nothing to do here. - (*env)->DeleteLocalRef(env, jVMBaseVal); - } else { - char buf[64]; - jstring jVMVal = NULL; - const char *baseVal = ""; - - /* user.xxx base property */ - if (platformDispVal) { - PUTPROP(props, baseKey, platformDispVal); - baseVal = platformDispVal; - } - - /* user.xxx.display property */ - jio_snprintf(buf, sizeof(buf), "%s.display", baseKey); - GETPROP(props, buf, jVMVal); - if (jVMVal == NULL) { - if (platformDispVal && (strcmp(baseVal, platformDispVal) != 0)) { - PUTPROP(props, buf, platformDispVal); - } - } else { - (*env)->DeleteLocalRef(env, jVMVal); - } - - /* user.xxx.format property */ - jio_snprintf(buf, sizeof(buf), "%s.format", baseKey); - GETPROP(props, buf, jVMVal); - if (jVMVal == NULL) { - if (platformFmtVal && (strcmp(baseVal, platformFmtVal) != 0)) { - PUTPROP(props, buf, platformFmtVal); - } - } else { - (*env)->DeleteLocalRef(env, jVMVal); - } +/* + * Store the UTF-8 string encoding of the value in the array + * at the index if the value is non-null. Store nothing if the value is null. + * On any error, return from Java_jdk_internal_util_SystemProps_00024Raw_platformProperties. + */ +#define PUTPROP(array, prop_index, val) \ + if (val != NULL) { \ + jstring jval = (*env)->NewStringUTF(env, val); \ + if (jval == NULL) \ + return NULL; \ + (*env)->SetObjectArrayElement(env, array, jdk_internal_util_SystemProps_Raw_##prop_index, jval); \ + if ((*env)->ExceptionOccurred(env)) \ + return NULL; \ + (*env)->DeleteLocalRef(env, jval); \ } - return NULL; -} +/* + * Store the Platform string encoding of the value in the array + * at the index if the value is non-null. Store nothing if the value is null. + * On any error, return from Java_jdk_internal_util_SystemProps_00024Raw_platformProperties. + */ +#define PUTPROP_PlatformString(array, prop_index, val) \ + if (val != NULL) { \ + jstring jval = GetStringPlatform(env, val); \ + if (jval == NULL) \ + return NULL; \ + (*env)->SetObjectArrayElement(env, array, jdk_internal_util_SystemProps_Raw_##prop_index, jval); \ + if ((*env)->ExceptionOccurred(env)) \ + return NULL; \ + (*env)->DeleteLocalRef(env, jval); \ + } -JNIEXPORT jobject JNICALL -Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props) +/* + * Gather the system properties and return as a String[]. + * The first FIXED_LENGTH entries are the platform defined property values, no names. + * The remaining array indices are alternating key/value pairs + * supplied by the VM including those defined on the command line + * using -Dkey=value that may override the platform defined value. + * The caller is responsible for replacing platform provided values as needed. + * + * Class: jdk_internal_util_SystemProps_Raw + * Method: platformProperties + * Signature: ()[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL +Java_jdk_internal_util_SystemProps_00024Raw_platformProperties(JNIEnv *env, jclass cla) { - char buf[128]; java_props_t *sprops; - jmethodID putID, removeID, getPropID; - jobject ret = NULL; - jstring jVMVal = NULL; + jobject propArray = NULL; + jclass classString; + int nstrings = jdk_internal_util_SystemProps_Raw_FIXED_LENGTH; - if ((*env)->EnsureLocalCapacity(env, 50) < 0) { - return NULL; - } + // Get the platform specific values sprops = GetJavaProperties(env); CHECK_NULL_RETURN(sprops, NULL); - putID = (*env)->GetMethodID(env, - (*env)->GetObjectClass(env, props), - "put", - "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); - CHECK_NULL_RETURN(putID, NULL); - - removeID = (*env)->GetMethodID(env, - (*env)->GetObjectClass(env, props), - "remove", - "(Ljava/lang/Object;)Ljava/lang/Object;"); - CHECK_NULL_RETURN(removeID, NULL); - - getPropID = (*env)->GetMethodID(env, - (*env)->GetObjectClass(env, props), - "getProperty", - "(Ljava/lang/String;)Ljava/lang/String;"); - CHECK_NULL_RETURN(getPropID, NULL); - - PUTPROP(props, "java.specification.version", - VERSION_SPECIFICATION); - PUTPROP(props, "java.specification.name", - "Java Platform API Specification"); - PUTPROP(props, "java.specification.vendor", - JAVA_SPECIFICATION_VENDOR); - - PUTPROP(props, "java.vendor", VENDOR); - PUTPROP(props, "java.vendor.url", VENDOR_URL); - PUTPROP(props, "java.vendor.url.bug", VENDOR_URL_BUG); - - jio_snprintf(buf, sizeof(buf), "%d.%d", JVM_CLASSFILE_MAJOR_VERSION, - JVM_CLASSFILE_MINOR_VERSION); - PUTPROP(props, "java.class.version", buf); + /* + * !!! DO NOT call PUTPROP_PlatformString (NewStringPlatform) before this line !!! + */ + InitializeEncoding(env, sprops->sun_jnu_encoding); - if (sprops->awt_toolkit) { - PUTPROP(props, "awt.toolkit", sprops->awt_toolkit); - } -#ifdef MACOSX - if (sprops->awt_headless) { - PUTPROP(props, "java.awt.headless", sprops->awt_headless); + // Ensure capacity for the array and for a string for each fixed length element + if ((*env)->EnsureLocalCapacity(env, nstrings + 2) < 0) { + return NULL; } -#endif + + // Allocate an array of String for all the well known props + classString = JNU_ClassString(env); + CHECK_NULL_RETURN(classString, NULL); + + propArray = (*env)->NewObjectArray(env, nstrings, classString, NULL); + CHECK_NULL_RETURN(propArray, NULL); /* os properties */ - PUTPROP(props, "os.name", sprops->os_name); - PUTPROP(props, "os.version", sprops->os_version); - PUTPROP(props, "os.arch", sprops->os_arch); + PUTPROP(propArray, _os_name_NDX, sprops->os_name); + PUTPROP(propArray, _os_version_NDX, sprops->os_version); + PUTPROP(propArray, _os_arch_NDX, sprops->os_arch); #ifdef JDK_ARCH_ABI_PROP_NAME - PUTPROP(props, "sun.arch.abi", sprops->sun_arch_abi); + PUTPROP(propArray, _sun_arch_abi_NDX, sprops->sun_arch_abi); #endif /* file system properties */ - PUTPROP(props, "file.separator", sprops->file_separator); - PUTPROP(props, "path.separator", sprops->path_separator); - PUTPROP(props, "line.separator", sprops->line_separator); + PUTPROP(propArray, _file_separator_NDX, sprops->file_separator); + PUTPROP(propArray, _path_separator_NDX, sprops->path_separator); + PUTPROP(propArray, _line_separator_NDX, sprops->line_separator); + + PUTPROP(propArray, _file_encoding_NDX, sprops->encoding); + PUTPROP(propArray, _sun_jnu_encoding_NDX, sprops->sun_jnu_encoding); /* * file encoding for stdout and stderr */ - if (sprops->sun_stdout_encoding != NULL) { - PUTPROP(props, "sun.stdout.encoding", sprops->sun_stdout_encoding); - } - if (sprops->sun_stderr_encoding != NULL) { - PUTPROP(props, "sun.stderr.encoding", sprops->sun_stderr_encoding); - } + PUTPROP(propArray, _sun_stdout_encoding_NDX, sprops->sun_stdout_encoding); + PUTPROP(propArray, _sun_stderr_encoding_NDX, sprops->sun_stderr_encoding); /* unicode_encoding specifies the default endianness */ - PUTPROP(props, "sun.io.unicode.encoding", sprops->unicode_encoding); - if (sprops->cpu_isalist != NULL) { - // leave undefined if none - PUTPROP(props, "sun.cpu.isalist", sprops->cpu_isalist); - } - PUTPROP(props, "sun.cpu.endian", sprops->cpu_endian); - + PUTPROP(propArray, _sun_io_unicode_encoding_NDX, sprops->unicode_encoding); + PUTPROP(propArray, _sun_cpu_endian_NDX, sprops->cpu_endian); + PUTPROP(propArray, _sun_cpu_isalist_NDX, sprops->cpu_isalist); #ifdef MACOSX + PUTPROP(propArray, _java_awt_headless_NDX, sprops->awt_headless); + /* Proxy setting properties */ if (sprops->httpProxyEnabled) { - PUTPROP(props, "http.proxyHost", sprops->httpHost); - PUTPROP(props, "http.proxyPort", sprops->httpPort); + PUTPROP(propArray, _http_proxyHost_NDX, sprops->httpHost); + PUTPROP(propArray, _http_proxyPort_NDX, sprops->httpPort); } if (sprops->httpsProxyEnabled) { - PUTPROP(props, "https.proxyHost", sprops->httpsHost); - PUTPROP(props, "https.proxyPort", sprops->httpsPort); + PUTPROP(propArray, _https_proxyHost_NDX, sprops->httpsHost); + PUTPROP(propArray, _https_proxyPort_NDX, sprops->httpsPort); } if (sprops->ftpProxyEnabled) { - PUTPROP(props, "ftp.proxyHost", sprops->ftpHost); - PUTPROP(props, "ftp.proxyPort", sprops->ftpPort); + PUTPROP(propArray, _ftp_proxyHost_NDX, sprops->ftpHost); + PUTPROP(propArray, _ftp_proxyPort_NDX, sprops->ftpPort); } if (sprops->socksProxyEnabled) { - PUTPROP(props, "socksProxyHost", sprops->socksHost); - PUTPROP(props, "socksProxyPort", sprops->socksPort); + PUTPROP(propArray, _socksProxyHost_NDX, sprops->socksHost); + PUTPROP(propArray, _socksProxyPort_NDX, sprops->socksPort); } if (sprops->gopherProxyEnabled) { // The gopher client is different in that it expects an 'is this set?' flag that the others don't. - PUTPROP(props, "gopherProxySet", "true"); - PUTPROP(props, "gopherProxyHost", sprops->gopherHost); - PUTPROP(props, "gopherProxyPort", sprops->gopherPort); + PUTPROP(propArray, _gopherProxySet_NDX, "true"); + PUTPROP(propArray, _gopherProxyHost_NDX, sprops->gopherHost); + PUTPROP(propArray, _gopherProxyPort_NDX, sprops->gopherPort); } else { - PUTPROP(props, "gopherProxySet", "false"); + PUTPROP(propArray, _gopherProxySet_NDX, "false"); } // Mac OS X only has a single proxy exception list which applies // to all protocols if (sprops->exceptionList) { - PUTPROP(props, "http.nonProxyHosts", sprops->exceptionList); - PUTPROP(props, "ftp.nonProxyHosts", sprops->exceptionList); - PUTPROP(props, "socksNonProxyHosts", sprops->exceptionList); + PUTPROP(propArray, _http_nonProxyHosts_NDX, sprops->exceptionList); + PUTPROP(propArray, _ftp_nonProxyHosts_NDX, sprops->exceptionList); + PUTPROP(propArray, _socksNonProxyHosts_NDX, sprops->exceptionList); } #endif - /* !!! DO NOT call PUTPROP_ForPlatformNString before this line !!! - * !!! The platform native encoding for strings has not been set up yet !!! - */ - InitializeEncoding(env, sprops->sun_jnu_encoding); + /* data model */ + if (sizeof(sprops) == 4) { + sprops->data_model = "32"; + } else if (sizeof(sprops) == 8) { + sprops->data_model = "64"; + } else { + sprops->data_model = "unknown"; + } + PUTPROP(propArray, _sun_arch_data_model_NDX, sprops->data_model); + + /* patch level */ + PUTPROP(propArray, _sun_os_patch_level_NDX, sprops->patch_level); /* Printing properties */ /* Note: java.awt.printerjob is an implementation private property which @@ -317,24 +226,9 @@ * find and load classes that are part of the JRE. * This property may be removed if that mechanism is redesigned */ - PUTPROP(props, "java.awt.printerjob", sprops->printerJob); + PUTPROP(propArray, _java_awt_printerjob_NDX, sprops->printerJob); - /* data model */ - if (sizeof(sprops) == 4) { - sprops->data_model = "32"; - } else if (sizeof(sprops) == 8) { - sprops->data_model = "64"; - } else { - sprops->data_model = "unknown"; - } - PUTPROP(props, "sun.arch.data.model", \ - sprops->data_model); - - /* patch level */ - if (sprops->patch_level != NULL) { - PUTPROP(props, "sun.os.patch.level", \ - sprops->patch_level); - } + PUTPROP(propArray, _awt_toolkit_NDX, sprops->awt_toolkit); /* Java2D properties */ /* Note: java.awt.graphicsenv is an implementation private property which @@ -347,55 +241,53 @@ * find and load classes that are part of the JRE. * This property may be removed if that mechanism is redesigned */ - PUTPROP(props, "java.awt.graphicsenv", sprops->graphics_env); - if (sprops->font_dir != NULL) { - PUTPROP_ForPlatformNString(props, - "sun.java2d.fontpath", sprops->font_dir); - } - - PUTPROP_ForPlatformNString(props, "java.io.tmpdir", sprops->tmp_dir); - - PUTPROP_ForPlatformNString(props, "user.name", sprops->user_name); - PUTPROP_ForPlatformNString(props, "user.home", sprops->user_home); - PUTPROP_ForPlatformNString(props, "user.dir", sprops->user_dir); + PUTPROP(propArray, _java_awt_graphicsenv_NDX, sprops->graphics_env); + PUTPROP_PlatformString(propArray, _sun_java2d_fontpath_NDX, sprops->font_dir); - /* This is a sun. property as it is currently only set for Gnome and - * Windows desktops. + /* + * The sun.desktop property is currently only set for Gnome and Windows desktops. */ - if (sprops->desktop != NULL) { - PUTPROP(props, "sun.desktop", sprops->desktop); - } + PUTPROP(propArray, _sun_desktop_NDX, sprops->desktop); - ret = JVM_InitProperties(env, props); + PUTPROP_PlatformString(propArray, _java_io_tmpdir_NDX, sprops->tmp_dir); - /* reconstruct i18n related properties */ - fillI18nProps(env, props, "user.language", sprops->display_language, - sprops->format_language, putID, getPropID); - fillI18nProps(env, props, "user.script", - sprops->display_script, sprops->format_script, putID, getPropID); - fillI18nProps(env, props, "user.country", - sprops->display_country, sprops->format_country, putID, getPropID); - fillI18nProps(env, props, "user.variant", - sprops->display_variant, sprops->format_variant, putID, getPropID); - GETPROP(props, "file.encoding", jVMVal); - if (jVMVal == NULL) { -#ifdef MACOSX - /* - * Since sun_jnu_encoding is now hard-coded to UTF-8 on Mac, we don't - * want to use it to overwrite file.encoding - */ - PUTPROP(props, "file.encoding", sprops->encoding); -#else - PUTPROP(props, "file.encoding", sprops->sun_jnu_encoding); -#endif - } else { - (*env)->DeleteLocalRef(env, jVMVal); - } + PUTPROP_PlatformString(propArray, _user_name_NDX, sprops->user_name); + PUTPROP_PlatformString(propArray, _user_home_NDX, sprops->user_home); + PUTPROP_PlatformString(propArray, _user_dir_NDX, sprops->user_dir); + + /* + * Set i18n related property fields from platform. + */ + PUTPROP(propArray, _display_language_NDX, sprops->display_language); + PUTPROP(propArray, _display_script_NDX, sprops->display_script); + PUTPROP(propArray, _display_country_NDX, sprops->display_country); + PUTPROP(propArray, _display_variant_NDX, sprops->display_variant); + + PUTPROP(propArray, _format_language_NDX, sprops->format_language); + PUTPROP(propArray, _format_script_NDX, sprops->format_script); + PUTPROP(propArray, _format_country_NDX, sprops->format_country); + PUTPROP(propArray, _format_variant_NDX, sprops->format_variant); - // Platform defined encoding properties override any on the command line - PUTPROP(props, "sun.jnu.encoding", sprops->sun_jnu_encoding); + return propArray; +} - return ret; +/* + * Gather the VM and command line properties and return as a String[]. + * The array indices are alternating key/value pairs + * supplied by the VM including those defined on the command line + * using -Dkey=value that may override the platform defined value. + * + * Note: The platform encoding must have been set. + * + * Class: jdk_internal_util_SystemProps_Raw + * Method: vmProperties + * Signature: ()[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL +Java_jdk_internal_util_SystemProps_00024Raw_vmProperties(JNIEnv *env, jclass cla) +{ + jobjectArray cmdProps = JVM_GetProperties(env); + return cmdProps; } /* --- old/test/jdk/java/lang/System/PropertyTest.java 2018-11-19 18:30:46.508435257 -0500 +++ new/test/jdk/java/lang/System/PropertyTest.java 2018-11-19 18:30:46.344434444 -0500 @@ -56,8 +56,8 @@ return new Object[][]{ {"java.version"}, {"java.version.date"}, - // {"java.vendor"}, - // {"java.vendor.url"}, + // {"java.vendor"}, // open builds may not have a vendor unless configured + {"java.vendor.url.bug"}, {"java.home"}, {"java.vm.specification.version"}, {"java.vm.specification.vendor"}, --- /dev/null 2018-11-13 07:50:04.032081978 -0500 +++ new/src/java.base/share/classes/jdk/internal/util/SystemProps.java 2018-11-19 18:30:47.096438173 -0500 @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2018, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.util; + + +import java.lang.annotation.Native; +import java.util.Properties; + +/** + * System Property initialization for internal use only + * Retrieves the platform, JVM, and command line properties, + * applies initial defaults and returns the Properties instance + * that becomes the System.getProperties instance. + */ +public final class SystemProps { + + // no instances + private SystemProps() {} + + /** + * Create and initialize the system properties from the native properties + * and command line properties. + * Note: Build-defined properties such as versions and vendor information + * are initialized by VersionProps.java-template. + * + * @return a Properties instance initialized with all of the properties + */ + public static Properties initProperties() { + // Initially, cmdProperties only includes -D and props from the VM + Raw raw = new Raw(); + Properties props = raw.cmdProperties(); + + String javaHome = props.getProperty("java.home"); + assert javaHome != null : "java.home not set"; + + putIfAbsent(props, "user.home", raw.propDefault(Raw._user_home_NDX)); + putIfAbsent(props, "user.dir", raw.propDefault(Raw._user_dir_NDX)); + putIfAbsent(props, "user.name", raw.propDefault(Raw._user_name_NDX)); + + // Platform defined encoding cannot be overridden on the command line + put(props, "sun.jnu.encoding", raw.propDefault(Raw._sun_jnu_encoding_NDX)); + + // Add properties that have not been overridden on the cmdline + putIfAbsent(props, "file.encoding", + ((raw.propDefault(Raw._file_encoding_NDX) == null) + ? raw.propDefault(Raw._sun_jnu_encoding_NDX) + : raw.propDefault(Raw._file_encoding_NDX))); + + // Use platform values if not overridden by a commandline -Dkey=value + // In no particular order + putIfAbsent(props, "os.name", raw.propDefault(Raw._os_name_NDX)); + putIfAbsent(props, "os.arch", raw.propDefault(Raw._os_arch_NDX)); + putIfAbsent(props, "os.version", raw.propDefault(Raw._os_version_NDX)); + putIfAbsent(props, "line.separator", raw.propDefault(Raw._line_separator_NDX)); + putIfAbsent(props, "file.separator", raw.propDefault(Raw._file_separator_NDX)); + putIfAbsent(props, "path.separator", raw.propDefault(Raw._path_separator_NDX)); + putIfAbsent(props, "java.io.tmpdir", raw.propDefault(Raw._java_io_tmpdir_NDX)); + putIfAbsent(props, "http.proxyHost", raw.propDefault(Raw._http_proxyHost_NDX)); + putIfAbsent(props, "http.proxyPort", raw.propDefault(Raw._http_proxyPort_NDX)); + putIfAbsent(props, "https.proxyHost", raw.propDefault(Raw._https_proxyHost_NDX)); + putIfAbsent(props, "https.proxyPort", raw.propDefault(Raw._https_proxyPort_NDX)); + putIfAbsent(props, "ftp.proxyHost", raw.propDefault(Raw._ftp_proxyHost_NDX)); + putIfAbsent(props, "ftp.proxyPort", raw.propDefault(Raw._ftp_proxyPort_NDX)); + putIfAbsent(props, "socksProxyHost", raw.propDefault(Raw._socksProxyHost_NDX)); + putIfAbsent(props, "socksProxyPort", raw.propDefault(Raw._socksProxyPort_NDX)); + putIfAbsent(props, "gopherProxySet", raw.propDefault(Raw._gopherProxySet_NDX)); + putIfAbsent(props, "gopherProxyHost", raw.propDefault(Raw._gopherProxyHost_NDX)); + putIfAbsent(props, "gopherProxyPort", raw.propDefault(Raw._gopherProxyPort_NDX)); + putIfAbsent(props, "http.nonProxyHosts", raw.propDefault(Raw._http_nonProxyHosts_NDX)); + putIfAbsent(props, "ftp.nonProxyHosts", raw.propDefault(Raw._ftp_nonProxyHosts_NDX)); + putIfAbsent(props, "socksNonProxyHosts", raw.propDefault(Raw._socksNonProxyHosts_NDX)); + putIfAbsent(props, "awt.toolkit", raw.propDefault(Raw._awt_toolkit_NDX)); + putIfAbsent(props, "java.awt.headless", raw.propDefault(Raw._java_awt_headless_NDX)); + putIfAbsent(props, "java.awt.printerjob", raw.propDefault(Raw._java_awt_printerjob_NDX)); + putIfAbsent(props, "java.awt.graphicsenv", raw.propDefault(Raw._java_awt_graphicsenv_NDX)); + putIfAbsent(props, "sun.desktop", raw.propDefault(Raw._sun_desktop_NDX)); + putIfAbsent(props, "sun.java2d.fontpath", raw.propDefault(Raw._sun_java2d_fontpath_NDX)); + putIfAbsent(props, "sun.arch.abi", raw.propDefault(Raw._sun_arch_abi_NDX)); + putIfAbsent(props, "sun.arch.data.model", raw.propDefault(Raw._sun_arch_data_model_NDX)); + putIfAbsent(props, "sun.os.patch.level", raw.propDefault(Raw._sun_os_patch_level_NDX)); + putIfAbsent(props, "sun.stdout.encoding", raw.propDefault(Raw._sun_stdout_encoding_NDX)); + putIfAbsent(props, "sun.stderr.encoding", raw.propDefault(Raw._sun_stderr_encoding_NDX)); + putIfAbsent(props, "sun.io.unicode.encoding", raw.propDefault(Raw._sun_io_unicode_encoding_NDX)); + putIfAbsent(props, "sun.cpu.isalist", raw.propDefault(Raw._sun_cpu_isalist_NDX)); + putIfAbsent(props, "sun.cpu.endian", raw.propDefault(Raw._sun_cpu_endian_NDX)); + + /* Construct i18n related options */ + fillI18nProps(props,"user.language", raw.propDefault(Raw._display_language_NDX), + raw.propDefault(Raw._format_language_NDX)); + fillI18nProps(props,"user.script", raw.propDefault(Raw._display_script_NDX), + raw.propDefault(Raw._format_script_NDX)); + fillI18nProps(props,"user.country", raw.propDefault(Raw._display_country_NDX), + raw.propDefault(Raw._format_country_NDX)); + fillI18nProps(props,"user.variant", raw.propDefault(Raw._display_variant_NDX), + raw.propDefault(Raw._format_variant_NDX)); + + return props; + } + + /** + * Puts the property if it is non-null + * @param props the Properties + * @param key the key + * @param value the value + */ + private static void put(Properties props, String key, String value) { + if (value != null) { + props.put(key, value); + } + } + + /** + * Puts the property if it is non-null and is not already in the Properties. + * @param props the Properties + * @param key the key + * @param value the value + */ + private static void putIfAbsent(Properties props, String key, String value) { + if (value != null) { + props.putIfAbsent(key, value); + } + } + + /** + * For internationalization options, compute the values for + * display and format properties + * MUST NOT override command line defined values. + * + * @param base the base property name + * @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, + String format) { + // Do not override command line setting + String baseValue = cmdProps.getProperty(base); + if (baseValue == null) { + // Not overridden on the command line; define the properties if there are platform defined values + baseValue = display; + } + if (baseValue != null) { + cmdProps.put(base, baseValue); + } + + /* user.xxx.display property */ + String disp = base + ".display"; + String dispValue = cmdProps.getProperty(disp); + if (dispValue == null && display != null && !display.equals(baseValue)) { + // Create the property only if different from the base property + cmdProps.put(disp, display); + } + + /* user.xxx.format property */ + String fmt = base + ".format"; + String fmtValue = cmdProps.getProperty(fmt); + if (fmtValue == null && format != null && !format.equals(baseValue)) { + // Create the property only if different than the base property + cmdProps.put(fmt, format); + } + } + + /** + * Read the raw properties from native System.c. + */ + public static class Raw { + // Array indices written by native vmProperties() + // The order is arbitrary (but alphabetic for convenience) + @Native private static final int _awt_toolkit_NDX = 0; + @Native private static final int _display_country_NDX = 1 + _awt_toolkit_NDX; + @Native private static final int _display_language_NDX = 1 + _display_country_NDX; + @Native private static final int _display_script_NDX = 1 + _display_language_NDX; + @Native private static final int _display_variant_NDX = 1 + _display_script_NDX; + @Native private static final int _file_encoding_NDX = 1 + _display_variant_NDX; + @Native private static final int _file_separator_NDX = 1 + _file_encoding_NDX; + @Native private static final int _format_country_NDX = 1 + _file_separator_NDX; + @Native private static final int _format_language_NDX = 1 + _format_country_NDX; + @Native private static final int _format_script_NDX = 1 + _format_language_NDX; + @Native private static final int _format_variant_NDX = 1 + _format_script_NDX; + @Native private static final int _ftp_nonProxyHosts_NDX = 1 + _format_variant_NDX; + @Native private static final int _ftp_proxyHost_NDX = 1 + _ftp_nonProxyHosts_NDX; + @Native private static final int _ftp_proxyPort_NDX = 1 + _ftp_proxyHost_NDX; + @Native private static final int _gopherProxyHost_NDX = 1 + _ftp_proxyPort_NDX; + @Native private static final int _gopherProxyPort_NDX = 1 + _gopherProxyHost_NDX; + @Native private static final int _gopherProxySet_NDX = 1 + _gopherProxyPort_NDX; + @Native private static final int _http_nonProxyHosts_NDX = 1 + _gopherProxySet_NDX; + @Native private static final int _http_proxyHost_NDX = 1 + _http_nonProxyHosts_NDX; + @Native private static final int _http_proxyPort_NDX = 1 + _http_proxyHost_NDX; + @Native private static final int _https_proxyHost_NDX = 1 + _http_proxyPort_NDX; + @Native private static final int _https_proxyPort_NDX = 1 + _https_proxyHost_NDX; + @Native private static final int _java_awt_graphicsenv_NDX = 1 + _https_proxyPort_NDX; + @Native private static final int _java_awt_printerjob_NDX = 1 + _java_awt_graphicsenv_NDX; + @Native private static final int _java_awt_headless_NDX = 1 + _java_awt_printerjob_NDX; + @Native private static final int _java_io_tmpdir_NDX = 1 + _java_awt_headless_NDX; + @Native private static final int _line_separator_NDX = 1 + _java_io_tmpdir_NDX; + @Native private static final int _os_arch_NDX = 1 + _line_separator_NDX; + @Native private static final int _os_name_NDX = 1 + _os_arch_NDX; + @Native private static final int _os_version_NDX = 1 + _os_name_NDX; + @Native private static final int _path_separator_NDX = 1 + _os_version_NDX; + @Native private static final int _socksNonProxyHosts_NDX = 1 + _path_separator_NDX; + @Native private static final int _socksProxyHost_NDX = 1 + _socksNonProxyHosts_NDX; + @Native private static final int _socksProxyPort_NDX = 1 + _socksProxyHost_NDX; + @Native private static final int _sun_arch_abi_NDX = 1 + _socksProxyPort_NDX; + @Native private static final int _sun_arch_data_model_NDX = 1 + _sun_arch_abi_NDX; + @Native private static final int _sun_cpu_endian_NDX = 1 + _sun_arch_data_model_NDX; + @Native private static final int _sun_cpu_isalist_NDX = 1 + _sun_cpu_endian_NDX; + @Native private static final int _sun_desktop_NDX = 1 + _sun_cpu_isalist_NDX; + @Native private static final int _sun_io_unicode_encoding_NDX = 1 + _sun_desktop_NDX; + @Native private static final int _sun_java2d_fontpath_NDX = 1 + _sun_io_unicode_encoding_NDX; + @Native private static final int _sun_jnu_encoding_NDX = 1 + _sun_java2d_fontpath_NDX; + @Native private static final int _sun_os_patch_level_NDX = 1 + _sun_jnu_encoding_NDX; + @Native private static final int _sun_stderr_encoding_NDX = 1 + _sun_os_patch_level_NDX; + @Native private static final int _sun_stdout_encoding_NDX = 1 + _sun_stderr_encoding_NDX; + @Native private static final int _user_dir_NDX = 1 + _sun_stdout_encoding_NDX; + @Native private static final int _user_home_NDX = 1 + _user_dir_NDX; + @Native private static final int _user_name_NDX = 1 + _user_home_NDX; + @Native private static final int FIXED_LENGTH = 1 + _user_name_NDX; + + // Array of Strings returned from the VM and Command line properties + // The array is not used after initialization is complete. + private final String[] platformProps; + + private Raw() { + platformProps = platformProperties(); + } + + /** + * Return the value for a well known default from native. + * @param index the index of the known property + * @return the value + */ + String propDefault(int index) { + return platformProps[index]; + } + + /** + * Return a Properties instance of the command line and VM options + * defined by name and value. + * The Properties instance is sized to include the fixed properties. + * + * @return return a Properties instance of the command line and VM options + */ + private Properties 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]; + if (k != null) { + String v = vmProps[i * 2 + 1]; + cmdProps.setProperty(k, v != null ? v : ""); + } else { + // no more key/value pairs + break; + } + } + return cmdProps; + } + + /** + * Returns the available VM and Command Line Properties. + * The VM supplies some key/value pairs and processes the command line + * to extract key/value pairs from the {@code "-Dkey=value"} arguments. + * + * @return an array of strings, with alternating key and value strings. + * Either keys or values may be null, the array may not be full. + * The first null key indicates there are no more key, value pairs. + */ + private static native String[] vmProperties(); + + /** + * Returns the platform specific property values identified + * by {@code "_xxx_NDX"} indexes. + * The indexes are strictly private, to be shared only with the native code. + * + * @return a array of strings, the properties are indexed by the {@code _xxx_NDX} + * indexes. The values are Strings and may be null. + */ + private static native String[] platformProperties(); + } +} --- /dev/null 2018-11-13 07:50:04.032081978 -0500 +++ new/test/jdk/java/lang/System/VerifyRawIndexesTest.java 2018-11-19 18:30:47.856441941 -0500 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.internal.util.SystemProps.Raw; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + + +/* + * @test + * @summary Test to verify that the Raw _xxx_NDX indices are unique and without gaps. + * @modules java.base/jdk.internal.util:+open + * @run testng VerifyRawIndexesTest + */ + +@Test +public class VerifyRawIndexesTest { + + /** + * Check that the Raw._*_NDX indexes are sequential and followed by + * the FIXED_LENGTH value. + * It verifies there there are no gaps or duplication in the declarations. + */ + @Test + void verifyIndexes() { + Field[] fields = Raw.class.getDeclaredFields(); + int expectedModifiers = Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL; + + int next = 0; // indexes start at zero + for (Field f : fields) { + try { + int mods = f.getModifiers(); + String name = f.getName(); + if (((mods & expectedModifiers) == expectedModifiers) && + (name.endsWith("_NDX") || name.equals("FIXED_LENGTH"))) { + f.setAccessible(true); + int ndx = f.getInt(null); + System.out.printf("%s: %s%n", name, ndx); + Assert.assertEquals(ndx, next, "index value wrong"); + next++; + } else { + System.out.printf("Ignoring field: " + f); + } + } catch (IllegalAccessException iae) { + Assert.fail("unexpected exception", iae); + } + } + } +}