--- old/src/share/vm/prims/jvmtiEnv.cpp 2016-08-04 08:30:59.754621658 -0400 +++ new/src/share/vm/prims/jvmtiEnv.cpp 2016-08-04 08:30:57.450676490 -0400 @@ -3560,28 +3560,34 @@ JvmtiEnv::GetSystemProperties(jint* count_ptr, char*** property_ptr) { jvmtiError err = JVMTI_ERROR_NONE; - *count_ptr = Arguments::PropertyList_count(Arguments::system_properties()); + // Get the number of readable properties. + *count_ptr = Arguments::PropertyList_readable_count(Arguments::system_properties()); + // Allocate memory to hold the exact number of readable properties. err = allocate(*count_ptr * sizeof(char *), (unsigned char **)property_ptr); if (err != JVMTI_ERROR_NONE) { return err; } - int i = 0 ; - for (SystemProperty* p = Arguments::system_properties(); p != NULL && i < *count_ptr; p = p->next(), i++) { - const char *key = p->key(); - char **tmp_value = *property_ptr+i; - err = allocate((strlen(key)+1) * sizeof(char), (unsigned char**)tmp_value); - if (err == JVMTI_ERROR_NONE) { - strcpy(*tmp_value, key); - } else { - // clean up previously allocated memory. - for (int j=0; jnext()) { + if (p->is_readable()) { + const char *key = p->key(); + char **tmp_value = *property_ptr+readable_count++; + err = allocate((strlen(key)+1) * sizeof(char), (unsigned char**)tmp_value); + if (err == JVMTI_ERROR_NONE) { + strcpy(*tmp_value, key); + } else { + // clean up previously allocated memory. + for (int j=0; j or matches property.=. -static bool is_matching_numbered_property(const char* option, const char* property, size_t len) { - if (strncmp(option, property, len) == 0) { - // Check for digits. - const char* sptr = option + len; - if (isdigit(*sptr)) { // Make sure next char is a digit. - while (isdigit(*sptr)) { - sptr++; - if (*sptr == '=' || *sptr == '\0') { - return true; - } - } - } - } - return false; -} - -// Return TRUE if option matches property or matches property=. -static bool is_matching_property(const char* option, const char* property, size_t len) { - return (strncmp(option, property, len) == 0) && (option[len] == '=' || option[len] == '\0'); -} - -// Return true if option_end is the name of a module-related java property -// with "-Djdk.module." removed. -static bool is_internal_module_property_end(const char* option_end) { - // For the repeating properties such as (-Djdk.module.patch.0 - // -Djdk.module.patch.1, etc) return true for ".[=]". - if (is_matching_numbered_property(option_end, ADDEXPORTS ".", ADDEXPORTS_LEN + 1) || - is_matching_numbered_property(option_end, ADDREADS ".", ADDREADS_LEN + 1) || - is_matching_numbered_property(option_end, PATCH ".", PATCH_LEN + 1)) { - return true; - } - return (is_matching_property(option_end, ADDMODS, ADDMODS_LEN) || - is_matching_property(option_end, LIMITMODS, LIMITMODS_LEN)); -} - -// Return true if the option is one of the module-related java properties -// that can only be set using the proper module-related option. -static bool is_module_property(const JavaVMOption *option) { - if (strncmp(option->optionString, "-D" MODULE_PROPERTY_PREFIX ".", MODULE_PROPERTY_PREFIX_LEN + 3) == 0) { - const char* option_end = option->optionString + MODULE_PROPERTY_PREFIX_LEN + 3; - return (is_internal_module_property_end(option_end) || - is_matching_property(option_end, PATH, PATH_LEN) || - is_matching_property(option_end, UPGRADE_PATH, UPGRADE_PATH_LEN)); - } - return false; -} - -// Return true if the option is one of the module-related java properties -// that can only be set using the proper module-related option and cannot -// be read by jvmti. -// It's expected that the caller removed the leading "-D" from 'option'. -bool Arguments::is_internal_module_property(const char* option) { - assert((strncmp(option, "-D", 2) != 0), "Unexpected leading -D"); - if (strncmp(option, MODULE_PROPERTY_PREFIX ".", MODULE_PROPERTY_PREFIX_LEN + 1) == 0) { - return is_internal_module_property_end(option + MODULE_PROPERTY_PREFIX_LEN + 1); - } - return false; -} - // Return true if any of the strings in null-terminated array 'names' matches. // If tail_allowed is true, then the tail must begin with a colon; otherwise, // the option must match exactly. @@ -238,6 +161,30 @@ } } +bool needs_module_property_warning = false; + +#define MODULE_PROPERTY_PREFIX "jdk.module" +#define MODULE_PROPERTY_PREFIX_LEN 10 +#define MODULE_MAIN_PROPERTY "jdk.module.main" +#define MODULE_MAIN_PROPERTY_LEN 15 + +// Return TRUE if option matches property, or property=, or property.. +static bool matches_property_prefix(const char* option, const char* property, size_t len) { + return (strncmp(option, property, len) == 0) && + (option[len] == '=' || option[len] == '.' || option[len] == '\0'); +} + +// Return true if the property is either "jdk.module" or starts with "jdk.module.", +// but does not start with "jdk.module.main". +// Return false if jdk.module.main because jdk.module.main and jdk.module.main.class +// are valid non-internal system properties. +// "property" should be passed without the leading "-D". +bool Arguments::is_internal_module_property(const char* property) { + assert((strncmp(property, "-D", 2) != 0), "Unexpected leading -D"); + return (matches_property_prefix(property, MODULE_PROPERTY_PREFIX, MODULE_PROPERTY_PREFIX_LEN) && + !matches_property_prefix(property, MODULE_MAIN_PROPERTY, MODULE_MAIN_PROPERTY_LEN)); +} + // Process java launcher properties. void Arguments::process_sun_java_launcher_properties(JavaVMInitArgs* args) { // See if sun.java.launcher, sun.java.launcher.is_altjvm or @@ -3166,9 +3113,11 @@ "-Djava.ext.dirs=%s is not supported. Use -classpath instead.\n", value); return JNI_EINVAL; } - // Silently ignore module related properties. They must be set using the modules - // options. For example: use "--add-modules java.sql", not "-Djdk.module.addmods=java.sql" - if (is_module_property(option)) { + // Check for module related properties. They must be set using the modules + // options. For example: use "--add-modules=java.sql", not + // "-Djdk.module.addmods=java.sql" + if (is_internal_module_property(option->optionString + 2)) { + needs_module_property_warning = true; continue; } @@ -3609,7 +3558,9 @@ // This needs to be done here, to prevent overwriting possible values written // to the jdk.module.addmods property by -javaagent and other options. if (add_modules_value != NULL) { - append_to_addmods_property(add_modules_value); + if (!append_to_addmods_property(add_modules_value)) { + return JNI_ENOMEM; + } } Arguments::set_bootclassloader_append_index(((int)strlen(Arguments::get_sysclasspath()))+1); @@ -4353,6 +4304,11 @@ hotspotrc, hotspotrc); } + if (needs_module_property_warning) { + warning("Ignoring system property options whose names start with '-Djdk.module'." + " They are reserved for internal use."); + } + #if defined(_ALLBSD_SOURCE) || defined(AIX) // UseLargePages is not yet supported on BSD and AIX. UNSUPPORTED_OPTION(UseLargePages); #endif @@ -4577,6 +4533,18 @@ return count; } +// Return the number of readable properties. +int Arguments::PropertyList_readable_count(SystemProperty* pl) { + int count = 0; + while(pl != NULL) { + if (pl->is_readable()) { + count++; + } + pl = pl->next(); + } + return count; +} + const char* Arguments::PropertyList_get_value(SystemProperty *pl, const char* key) { assert(key != NULL, "just checking"); SystemProperty* prop; @@ -4585,6 +4553,27 @@ } return NULL; } + +// Return the value of the requested property provided that it is a readable property. +const char* Arguments::PropertyList_get_readable_value(SystemProperty *pl, const char* key) { + assert(key != NULL, "just checking"); + SystemProperty* prop; + // Return the property value if the keys match and the property is not internal or + // it's the special internal property "jdk.boot.class.path.append". + for (prop = pl; prop != NULL; prop = prop->next()) { + if (strcmp(key, prop->key()) == 0) { + if (!prop->internal()) { + return prop->value(); + } else if (strcmp(key, "jdk.boot.class.path.append") == 0) { + return prop->value(); + } else { + // Property is internal and not jdk.boot.class.path.append so return NULL. + return NULL; + } + } + } + return NULL; +} const char* Arguments::PropertyList_get_key_at(SystemProperty *pl, int index) { int count = 0; --- old/src/share/vm/runtime/arguments.hpp 2016-08-04 08:31:31.980554830 -0400 +++ new/src/share/vm/runtime/arguments.hpp 2016-08-04 08:31:30.297705920 -0400 @@ -158,6 +158,10 @@ SystemProperty* next() const { return _next; } void set_next(SystemProperty* next) { _next = next; } + bool is_readable() const { + return !_internal || strcmp(_key, "jdk.boot.class.path.append") == 0; + } + // A system property should only have its value set // via an external interface if it is a writeable property. // The internal, non-writeable property jdk.boot.class.path.append @@ -748,7 +752,9 @@ PropertyAppendable append, PropertyWriteable writeable, PropertyInternal internal); static const char* PropertyList_get_value(SystemProperty* plist, const char* key); + static const char* PropertyList_get_readable_value(SystemProperty* plist, const char* key); static int PropertyList_count(SystemProperty* pl); + static int PropertyList_readable_count(SystemProperty* pl); static const char* PropertyList_get_key_at(SystemProperty* pl,int index); static char* PropertyList_get_value_at(SystemProperty* pl,int index); --- old/src/share/vm/utilities/ostream.cpp 2016-08-04 08:31:46.395094653 -0400 +++ new/src/share/vm/utilities/ostream.cpp 2016-08-04 08:31:44.657438793 -0400 @@ -703,13 +703,15 @@ // System properties don't generally contain newlines, so don't bother with unparsing. outputStream *text = xs->text(); for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { - // Print in two stages to avoid problems with long - // keys/values. assert(p->key() != NULL, "p->key() is NULL"); - text->print_raw(p->key()); - text->put('='); - assert(p->value() != NULL, "p->value() is NULL"); - text->print_raw_cr(p->value()); + if (p->is_readable()) { + // Print in two stages to avoid problems with long + // keys/values. + text->print_raw(p->key()); + text->put('='); + assert(p->value() != NULL, "p->value() is NULL"); + text->print_raw_cr(p->value()); + } } xs->tail("properties"); } --- old/test/compiler/c2/6852078/Test6852078.java 2016-08-04 08:32:03.292227213 -0400 +++ new/test/compiler/c2/6852078/Test6852078.java 2016-08-04 08:32:01.712503617 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2016, 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 @@ -29,7 +29,7 @@ * * @modules java.corba/com.sun.corba.se.impl.encoding * java.corba/com.sun.jndi.toolkit.corba - * @run main Test6852078 + * @run main/othervm --add-modules=java.corba Test6852078 */ import java.util.*; --- old/test/compiler/unsafe/UnsafeGetConstantField.java 2016-08-04 08:32:17.960225543 -0400 +++ new/test/compiler/unsafe/UnsafeGetConstantField.java 2016-08-04 08:32:16.285738744 -0400 @@ -40,7 +40,7 @@ * -XX:CompileCommand=dontinline,UnsafeGetConstantField.checkGetAddress() * -XX:CompileCommand=dontinline,*.test* * -XX:+UseUnalignedAccesses - * --add-reads=java.base=ALL-UNNAMED + * --add-reads=java.base=ALL-UNNAMED * compiler.unsafe.UnsafeGetConstantField * * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions @@ -50,7 +50,7 @@ * -XX:CompileCommand=dontinline,*.test* * -XX:CompileCommand=inline,*Unsafe.get* * -XX:-UseUnalignedAccesses - * --add-reads=java.base=ALL-UNNAMED + * --add-reads=java.base=ALL-UNNAMED * compiler.unsafe.UnsafeGetConstantField */ package compiler.unsafe; --- old/test/runtime/ErrorHandling/ProblematicFrameTest.java 2016-08-04 08:32:33.554319307 -0400 +++ new/test/runtime/ErrorHandling/ProblematicFrameTest.java 2016-08-04 08:32:31.951550015 -0400 @@ -48,7 +48,7 @@ public static void main(String[] args) throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-Xmx64m", "-XX:-TransmitErrorReport", "-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED", "-XX:-CreateCoredumpOnCrash", Crasher.class.getName()); + "-Xmx64m", "-XX:-TransmitErrorReport", "--add-exports:java.base/jdk.internal.misc=ALL-UNNAMED", "-XX:-CreateCoredumpOnCrash", Crasher.class.getName()); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldNotContain("Exception in thread"); output.shouldNotMatch("error occurred during error reporting \\(printing problematic frame\\)"); --- /dev/null 2016-07-26 09:06:09.265416988 -0400 +++ new/test/runtime/modules/ModuleOptionsWarn.java 2016-08-04 08:32:45.981881084 -0400 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016, 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. + */ + +/* + * @test + * @bug 8162415 + * @summary Test warnings for ignored properties. + * @modules java.base/jdk.internal.misc + * @library /testlibrary + */ + +import jdk.test.lib.*; + +// Test that the VM behaves correctly when processing command line module system properties. +public class ModuleOptionsWarn { + + public static void main(String[] args) throws Exception { + + // Test that a warning is issued for module related properties that get ignored. + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+PrintWarnings", "-Djdk.module.ignored", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Ignoring system property option"); + output.shouldHaveExitValue(0); + + // Test that a warning can be suppressed for module related properties that get ignored. + pb = ProcessTools.createJavaProcessBuilder( + "-Djdk.module.ignored", "-XX:-PrintWarnings", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Ignoring system property option"); + output.shouldHaveExitValue(0); + + // Test that a warning is not issued for properties of the form "jdk.module.main" + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+PrintWarnings", "-Djdk.module.main.ignored", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Ignoring system property option"); + output.shouldHaveExitValue(0); + } +}