--- old/src/share/vm/runtime/arguments.cpp 2015-08-06 16:29:03.749386922 -0400 +++ new/src/share/vm/runtime/arguments.cpp 2015-08-06 16:29:03.609388672 -0400 @@ -245,50 +245,56 @@ * * Over time -XX arguments may change. There are mechanisms to handle common cases: * - * ALIAS: An option may be renamed or replaced by another option. The old name can be supported by - * adding the old and new option names to the "aliased_jvm_flags" table. Delete the old - * variable from globals.hpp. This is often part of the process of deprecating a flag, but - * not all aliases need to be deprecated. + * ALIASED: An option that is simply another name for another option. This is often + * part of the process of deprecating a flag, but not all aliases need + * to be deprecated. + * + * Create an alias for an option by adding the old and new option names to the + * "aliased_jvm_flags" table. Delete the old variable from globals.hpp (etc),. + * + * DEPRECATED: An option that is supported, but a warning is printed to let the user know that + * support may be removed in the future. Both regular and aliased options may be + * deprecated. * - * DEPRECATED: An option may be supported, but a warning is printed to let the user know that support may - * be removed in the future. Both regular and aliased options may be deprecated. * Add a deprecation warning for an option (or alias) by adding an entry in the - * "deprecated_jvm_flags" table. Specify the option name, the jdk version that deprecated the - * option, and the jdk version that will expire the option (use "undefined()" if removal has - * been not scheduled). + * "deprecated_jvm_flags" table. Often an option "deprecated" in one major release will + * be made "obsolete" in the next. In this case the entry should be removed from the + * "deprecated_jvm_flags" table and added to the "obsolete_jvm_flags" table (see below). + * + * OBSOLETE: An option that has been removed (and deleted from globals.hpp), but is still accepted + * on the command line. A warning is printed to let the user know that option might not + * be accepted in the future. * - * OBSOLETE: An option may be removed (and deleted from globals.hpp), but still be accepted on the command - * line. A warning is printed to let the user know that support may be removed in the future. - * Add an obsolete warning for an option (or alias) by adding an entry in the - * "obsolete_jvm_flags" table. Specify the option name, the jdk version that obsoleted the option, - * and the jdk version that will expire the option (use "undefined()" if removal has been not - * scheduled). + * Add an obsolete warning for an option by adding an entry in the "obsolete_jvm_flags" + * table. + * + * EXPIRED: A deprecated or obsolete option that has an "accept_until" version less than or equal + * to the current JDK version. The system will flatly refuse to admit the existence of + * the flag. This allows a flag to die automatically over JDK releases. * - * EXPIRED: When the current JDK version is equal or greater to the "accept_until" version of a deprecated - * or obsolete option, the system will flatly refuse to admit the existence of the flag. This - * allows a flag to die correctly over JDK releases. * Note that manual cleanup of expired options should be done at major JDK version upgrades: - * - Expired options can be removed from the obsolete_jvm_flags, deprecated_jvm_flags tables, + * - Expired options should be removed from the obsolete_jvm_flags, deprecated_jvm_flags, * and aliased_jvm_flags tables. - * - Removed options may have global variable definitions that should also be - * removed (in globals.hpp, etc). + * - Expired deprecated options should have their global variable definitions removed + * (in globals.hpp, etc). * - * Tests: Aliases are tested in VMAliasOptions.java. - * Deprecated options are tested in VMDeprecatedOptions.java. - * Obsolete options are tested in various files. + * Tests: Aliases should be tested in VMAliasOptions.java. + * Deprecated options should be tested in VMDeprecatedOptions.java. */ // Obsolete or deprecated -XX flag. typedef struct { const char* name; - JDK_Version obsoleted_in; // When the warning started (obsolete or deprecated). + JDK_Version warning_started_in; // When the warning started (obsolete or deprecated). JDK_Version accept_until; // Which version to start denying the existence of the flag (if scheduled). } SpecialFlag; -// When a flag is eliminated, it can be added to this list in order to +// When a flag is made obsolete, it can be added to this list in order to // continue accepting this flag on the command-line, while issuing a warning // and ignoring the value. Once the JDK version reaches the 'accept_until' -// limit, we flatly refuse to admit the existence of the flag. +// limit, we flatly refuse to admit the existence of the flag. The 'accept_until' +// field can be set to undefined() if the expiration date has not yet been set. +// This table should be scrubbed of expired options on major JDK releases. static SpecialFlag const obsolete_jvm_flags[] = { { "UseOldInlining", JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "SafepointPollOffset", JDK_Version::jdk(9), JDK_Version::jdk(10) }, @@ -317,8 +323,12 @@ { NULL, JDK_Version(0), JDK_Version(0) } }; -// When a flag is deprecated, it can be added to this list in order to issuing a warning when the flag is used. +// When a flag is deprecated, it can be added to this list in order to issue a warning when the flag is used. // Once the JDK version reaches the 'accept_until' limit, we flatly refuse to admit the existence of the flag. +// The 'accept_until' field can be set to undefined() if the expiration date has not yet been set. +// If a deprecated option should be treated as obsolete before it is expired, it needs to be removed +// from this table and added to the obsolete_jvm_flags table. +// This table should be scrubbed of expired options on major JDK releases. static SpecialFlag const deprecated_jvm_flags[] = { // deprecated non-alias flags: { "MaxGCMinorPauseMillis", JDK_Version::jdk(8), JDK_Version::undefined() }, @@ -365,7 +375,7 @@ if ((strcmp(flag_status.name, flag_name) == 0)) { if (flag_status.accept_until.is_undefined() || JDK_Version::current().compare(flag_status.accept_until) == -1) { - *version = flag_status.obsoleted_in; + *version = flag_status.warning_started_in; return 1; } else { return -1; @@ -375,7 +385,7 @@ return 0; } -bool Arguments::is_newly_obsolete(const char *flag_name, JDK_Version* version) { +bool Arguments::is_obsolete_flag(const char *flag_name, JDK_Version* version) { return (is_special_flag(obsolete_jvm_flags, flag_name, version) == 1); } @@ -805,7 +815,7 @@ if (sscanf(arg, "-%" XSTR(BUFLEN) NAME_RANGE "%c", name, &dummy) == 1) { real_name = handle_aliases_and_deprecation(name, warn_if_deprecated); if (real_name == NULL) { - return false; // "name" is a deprecated option that has expired. + return false; } return set_bool_flag(real_name, false, origin); } @@ -1012,7 +1022,7 @@ strncpy(stripped_argname, argname, arg_len); stripped_argname[arg_len] = '\0'; // strncpy may not null terminate. - if (is_newly_obsolete(stripped_argname, &since)) { + if (is_obsolete_flag(stripped_argname, &since)) { char version[256]; since.to_string(version, sizeof(version)); warning("Ignoring option %s; support was removed in %s", stripped_argname, version); --- old/src/share/vm/runtime/arguments.hpp 2015-08-06 16:29:04.519377296 -0400 +++ new/src/share/vm/runtime/arguments.hpp 2015-08-06 16:29:04.387378946 -0400 @@ -423,9 +423,8 @@ // Returns true if the flag is obsolete and fits into the range specified // for being ignored. In the case the 'version' buffer is filled in with - // the version number when the flag became obsolete. Otherwise the flag has - // expired and should be ignored. - static bool is_newly_obsolete(const char* flag_name, JDK_Version* version); + // the version number when the flag became obsolete. + static bool is_obsolete_flag(const char* flag_name, JDK_Version* version); // Returns 1 if the flag is deprecated and jdk version is in the range specified. // In this case the 'version' buffer is filled in with the version number when @@ -434,10 +433,11 @@ // Returns 0 if the flag is not deprecated. static int is_deprecated_flag(const char* flag_name, JDK_Version* version); - // Return the real name for the flag passed on the command line. + // Return the real name for the flag passed on the command line (either an alias name or "flag_name"). static const char* real_flag_name(const char *flag_name); // Return the "real" name for option arg if arg is an alias, and print a warning if arg is deprecated. + // Return NULL if the arg has expired. static const char* handle_aliases_and_deprecation(const char* arg, bool warn); static short CompileOnlyClassesNum; --- old/test/testlibrary/jdk/test/lib/cli/CommandLineOptionTest.java 2015-08-06 16:29:05.265367969 -0400 +++ new/test/testlibrary/jdk/test/lib/cli/CommandLineOptionTest.java 2015-08-06 16:29:05.134369607 -0400 @@ -328,6 +328,140 @@ } /** + * Start VM with given options and values. + * Generates command line option flags from + * {@code optionNames} and {@code optionValues}. + * + * @param optionNames names of options to pass in + * @param optionValues values of options + * @param additionalVMOpts additional options that should be + * passed to JVM. + * @return output from vm process + */ + public static OutputAnalyzer startVMWithOptions(String[] optionNames, + String[] optionValues, + String... additionalVMOpts) throws Throwable { + List vmOpts = new ArrayList<>(); + if (optionNames == null || optionValues == null || optionNames.length != optionValues.length) { + throw new IllegalArgumentException("optionNames and/or optionValues"); + } + + for (int i = 0; i < optionNames.length; i++) { + vmOpts.add(prepareFlag(optionNames[i], optionValues[i])); + } + Collections.addAll(vmOpts, additionalVMOpts); + Collections.addAll(vmOpts, "-version"); + + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder( + vmOpts.toArray(new String[vmOpts.size()])); + + return new OutputAnalyzer(processBuilder.start()); + } + + /** + * Verifies from the output that values of specified JVM options were the same as + * expected values. + * + * @param outputAnalyzer search output for expect options and values. + * @param optionNames names of tested options. + * @param expectedValues expected values of tested options. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyOptionValuesFromOutput(OutputAnalyzer outputAnalyzer, + String[] optionNames, + String[] expectedValues) throws Throwable { + outputAnalyzer.shouldHaveExitValue(0); + for (int i = 0; i < optionNames.length; i++) { + outputAnalyzer.shouldMatch(String.format( + CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT, + optionNames[i], expectedValues[i])); + } + } + + /** + * Verifies that value of specified JVM options are the same as + * expected values. + * Generates command line option flags from + * {@code optionNames} and {@code expectedValues}. + * + * @param optionNames names of tested options. + * @param expectedValues expected values of tested options. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyOptionValues(String[] optionNames, + String[] expectedValues) throws Throwable { + OutputAnalyzer outputAnalyzer = startVMWithOptions(optionNames, expectedValues, "-XX:+PrintFlagsFinal"); + verifyOptionValuesFromOutput(outputAnalyzer, optionNames, expectedValues); + } + + /** + * Start VM with given options and values. + * Generates command line option flags from + * {@code optionNames} and {@code optionValues}. + * + * @param optionNames names of options to pass in + * @param optionValues values of options + * @param additionalVMOpts additional options that should be + * passed to JVM. + * @return output from vm process + */ + public static OutputAnalyzer startVMWithOptions(String[] optionNames, + String[] optionValues, + String... additionalVMOpts) throws Throwable { + List vmOpts = new ArrayList<>(); + if (optionNames == null || optionValues == null || optionNames.length != optionValues.length) { + throw new IllegalArgumentException("optionNames and/or optionValues"); + } + + for (int i = 0; i < optionNames.length; i++) { + vmOpts.add(prepareFlag(optionNames[i], optionValues[i])); + } + Collections.addAll(vmOpts, additionalVMOpts); + Collections.addAll(vmOpts, "-version"); + + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder( + vmOpts.toArray(new String[vmOpts.size()])); + + return new OutputAnalyzer(processBuilder.start()); + } + + /** + * Verifies from the output that values of specified JVM options were the same as + * expected values. + * + * @param outputAnalyzer search output for expect options and values. + * @param optionNames names of tested options. + * @param expectedValues expected values of tested options. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyOptionValuesFromOutput(OutputAnalyzer outputAnalyzer, + String[] optionNames, + String[] expectedValues) throws Throwable { + outputAnalyzer.shouldHaveExitValue(0); + for (int i = 0; i < optionNames.length; i++) { + outputAnalyzer.shouldMatch(String.format( + CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT, + optionNames[i], expectedValues[i])); + } + } + + /** + * Verifies that value of specified JVM options are the same as + * expected values. + * Generates command line option flags from + * {@code optionNames} and {@code expectedValues}. + * + * @param optionNames names of tested options. + * @param expectedValues expected values of tested options. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyOptionValues(String[] optionNames, + String[] expectedValues) throws Throwable { + OutputAnalyzer outputAnalyzer = startVMWithOptions(optionNames, expectedValues, "-XX:+PrintFlagsFinal"); + verifyOptionValuesFromOutput(outputAnalyzer, optionNames, expectedValues); + } + + /** * Verifies that value of specified JVM when type of newly started VM * is the same as the type of current. * This method filter out option with {@code optionName} @@ -379,6 +513,42 @@ } /** + * Prepares generic command line flag with name {@code name} by setting + * it's value to {@code value}. + * + * @param name the name of option to be prepared + * @param value the value of option ("+" or "-" can be used instead of "true" or "false") + * @return prepared command line flag + */ + public static String prepareFlag(String name, String value) { + if (value.equals("+") || value.equalsIgnoreCase("true")) { + return "-XX:+" + name; + } else if (value.equals("-") || value.equalsIgnoreCase("false")) { + return "-XX:-" + name; + } else { + return "-XX:" + name + "=" + value; + } + } + + /** + * Prepares generic command line flag with name {@code name} by setting + * it's value to {@code value}. + * + * @param name the name of option to be prepared + * @param value the value of option ("+" or "-" can be used instead of "true" or "false") + * @return prepared command line flag + */ + public static String prepareFlag(String name, String value) { + if (value.equals("+") || value.equalsIgnoreCase("true")) { + return "-XX:+" + name; + } else if (value.equals("-") || value.equalsIgnoreCase("false")) { + return "-XX:-" + name; + } else { + return "-XX:" + name + "=" + value; + } + } + + /** * Prepares generic command line flag with name {@code name} by setting * it's value to {@code value}. *