--- old/src/share/vm/runtime/arguments.cpp 2015-07-16 10:18:29.271560000 -0700 +++ new/src/share/vm/runtime/arguments.cpp 2015-07-16 10:18:29.176554000 -0700 @@ -91,7 +91,7 @@ int Arguments::_sun_java_launcher_pid = -1; bool Arguments::_sun_java_launcher_is_altjvm = false; -// These parameters are reset in method parse_vm_init_args(JavaVMInitArgs*) +// These parameters are reset in method parse_vm_init_args() bool Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods; bool Arguments::_UseOnStackReplacement = UseOnStackReplacement; bool Arguments::_BackgroundCompilation = BackgroundCompilation; @@ -2251,7 +2251,9 @@ // Parse JavaVMInitArgs structure -jint Arguments::parse_vm_init_args(const JavaVMInitArgs* args) { +jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args, + const JavaVMInitArgs *java_options_args, + const JavaVMInitArgs *cmd_line_args) { // For components of the system classpath. SysClassPath scp(Arguments::get_sysclasspath()); bool scp_assembly_required = false; @@ -2269,20 +2271,25 @@ // Setup flags for mixed which is the default set_mode_flags(_mixed); - // Parse JAVA_TOOL_OPTIONS environment variable (if present) - jint result = parse_java_tool_options_environment_variable(&scp, &scp_assembly_required); + // Parse args structure generated from JAVA_TOOL_OPTIONS environment + // variable (if present). + jint result = parse_each_vm_init_arg( + java_tool_options_args, &scp, &scp_assembly_required, Flag::ENVIRON_VAR); if (result != JNI_OK) { return result; } - // Parse JavaVMInitArgs structure passed in - result = parse_each_vm_init_arg(args, &scp, &scp_assembly_required, Flag::COMMAND_LINE); + // Parse args structure generated from the command line flags. + result = parse_each_vm_init_arg(cmd_line_args, &scp, &scp_assembly_required, + Flag::COMMAND_LINE); if (result != JNI_OK) { return result; } - // Parse _JAVA_OPTIONS environment variable (if present) (mimics classic VM) - result = parse_java_options_environment_variable(&scp, &scp_assembly_required); + // Parse args structure generated from the _JAVA_OPTIONS environment + // variable (if present) (mimics classic VM) + result = parse_each_vm_init_arg( + java_options_args, &scp, &scp_assembly_required, Flag::ENVIRON_VAR); if (result != JNI_OK) { return result; } @@ -3385,20 +3392,73 @@ return JNI_OK; } -jint Arguments::parse_java_options_environment_variable(SysClassPath* scp_p, bool* scp_assembly_required_p) { - return parse_options_environment_variable("_JAVA_OPTIONS", scp_p, - scp_assembly_required_p); +// Helper class for controlling the lifetime of JavaVMInitArgs +// objects. The contents of the JavaVMInitArgs are guaranteed to be +// deleted on the destruction of the ScopedVMInitArgs object. +class ScopedVMInitArgs : public StackObj { + private: + JavaVMInitArgs _args; + + public: + ScopedVMInitArgs() { + _args.version = JNI_VERSION_1_2; + _args.nOptions = 0; + _args.options = NULL; + _args.ignoreUnrecognized = false; + } + + // Populates the JavaVMInitArgs object represented by this + // ScopedVMInitArgs object with the arguments in options. The + // allocated memory is deleted by the destructor. If this method + // returns anything other than JNI_OK, then this object is in a + // partially constructed state, and should be abandoned. + jint set_args(GrowableArray* options) { + JavaVMOption* options_arr = NEW_C_HEAP_ARRAY_RETURN_NULL( + JavaVMOption, options->length(), mtInternal); + if (options_arr == NULL) { + return JNI_ENOMEM; + } + _args.options = options_arr; + + for (int i = 0; i < options->length(); i++) { + options_arr[i] = options->at(i); + options_arr[i].optionString = os::strdup(options_arr[i].optionString); + if (options_arr[i].optionString == NULL) { + // Rely on the destructor to do cleanup. + _args.nOptions = i; + return JNI_ENOMEM; + } + } + + _args.nOptions = options->length(); + _args.ignoreUnrecognized = IgnoreUnrecognizedVMOptions; + return JNI_OK; + } + + JavaVMInitArgs* get() { return &_args; } + + ~ScopedVMInitArgs() { + if (_args.options == NULL) return; + for (int i = 0; i < _args.nOptions; i++) { + os::free(_args.options[i].optionString); + } + FREE_C_HEAP_ARRAY(JavaVMOption, _args.options); + } +}; + +jint Arguments::parse_java_options_environment_variable(ScopedVMInitArgs* args) { + return parse_options_environment_variable("_JAVA_OPTIONS", args); } -jint Arguments::parse_java_tool_options_environment_variable(SysClassPath* scp_p, bool* scp_assembly_required_p) { - return parse_options_environment_variable("JAVA_TOOL_OPTIONS", scp_p, - scp_assembly_required_p); +jint Arguments::parse_java_tool_options_environment_variable(ScopedVMInitArgs* args) { + return parse_options_environment_variable("JAVA_TOOL_OPTIONS", args); } -jint Arguments::parse_options_environment_variable(const char* name, SysClassPath* scp_p, bool* scp_assembly_required_p) { +jint Arguments::parse_options_environment_variable(const char* name, + ScopedVMInitArgs* vm_args) { char *buffer = ::getenv(name); - // Don't check this variable if user has special privileges + // Don't check this environment variable if user has special privileges // (e.g. unix su command). if (buffer == NULL || os::have_special_privileges()) { return JNI_OK; @@ -3443,48 +3503,20 @@ *wrt++ = *rd++; // copy to option string } } - // Need to check if we're done before writing a NULL, - // because the write could be to the byte that rd is pointing to. - if (*rd++ == 0) { - *wrt = 0; - break; + if (*rd != 0) { + // In this case, the assignment to wrt below will make *rd nul, + // which will interfere with the next loop iteration. + rd++; } *wrt = 0; // Zero terminate option } - JavaVMOption* options_arr = - NEW_C_HEAP_ARRAY_RETURN_NULL(JavaVMOption, options->length(), mtInternal); - if (options_arr == NULL) { - delete options; - os::free(buffer); - return JNI_ENOMEM; - } - for (int i = 0; i < options->length(); i++) { - options_arr[i] = options->at(i); - } - // Construct JavaVMInitArgs structure and parse as if it was part of the command line - JavaVMInitArgs vm_args; - vm_args.version = JNI_VERSION_1_2; - vm_args.options = options_arr; - vm_args.nOptions = options->length(); - vm_args.ignoreUnrecognized = IgnoreUnrecognizedVMOptions; - - if (PrintVMOptions) { - const char* tail; - for (int i = 0; i < vm_args.nOptions; i++) { - const JavaVMOption *option = vm_args.options + i; - if (match_option(option, "-XX:", &tail)) { - logOption(tail); - } - } - } + // Fill out JavaVMInitArgs structure. + jint status = vm_args->set_args(options); - jint result = parse_each_vm_init_arg(&vm_args, scp_p, scp_assembly_required_p, - Flag::ENVIRON_VAR); - FREE_C_HEAP_ARRAY(JavaVMOption, options_arr); delete options; os::free(buffer); - return result; + return status; } void Arguments::set_shared_spaces_flags() { @@ -3567,32 +3599,18 @@ } #endif // PRODUCT -// Parse entry point called from JNI_CreateJavaVM - -jint Arguments::parse(const JavaVMInitArgs* args) { - - // Initialize ranges and constraints - CommandLineFlagRangeList::init(); - CommandLineFlagConstraintList::init(); - +static jint match_special_option_and_act(const JavaVMInitArgs* args, + char** flags_file) { // Remaining part of option string const char* tail; - // If flag "-XX:Flags=flags-file" is used it will be the first option to be processed. - const char* hotspotrc = ".hotspotrc"; - bool settings_file_specified = false; - bool needs_hotspotrc_warning = false; - - const char* flags_file; - int index; - for (index = 0; index < args->nOptions; index++) { - const JavaVMOption *option = args->options + index; + for (int index = 0; index < args->nOptions; index++) { + const JavaVMOption* option = args->options + index; if (ArgumentsExt::process_options(option)) { continue; } if (match_option(option, "-XX:Flags=", &tail)) { - flags_file = tail; - settings_file_specified = true; + *flags_file = (char *) tail; continue; } if (match_option(option, "-XX:+PrintVMOptions")) { @@ -3646,10 +3664,64 @@ } #endif } + return JNI_OK; +} + +static void print_options(const JavaVMInitArgs *args) { + const char* tail; + for (int index = 0; index < args->nOptions; index++) { + const JavaVMOption *option = args->options + index; + if (match_option(option, "-XX:", &tail)) { + logOption(tail); + } + } +} + +// Parse entry point called from JNI_CreateJavaVM + +jint Arguments::parse(const JavaVMInitArgs* args) { + // If flag "-XX:Flags=flags-file" is used it will be the first option to be processed. + const char* hotspotrc = ".hotspotrc"; + char* flags_file = NULL; + bool settings_file_specified = false; + bool needs_hotspotrc_warning = false; + ScopedVMInitArgs java_tool_options_args; + ScopedVMInitArgs java_options_args; + + jint code = + parse_java_tool_options_environment_variable(&java_tool_options_args); + if (code != JNI_OK) { + return code; + } + + code = parse_java_options_environment_variable(&java_options_args); + if (code != JNI_OK) { + return code; + } + + code = + match_special_option_and_act(java_tool_options_args.get(), &flags_file); + if (code != JNI_OK) { + return code; + } + + code = match_special_option_and_act(args, &flags_file); + if (code != JNI_OK) { + return code; + } + + code = match_special_option_and_act(java_options_args.get(), &flags_file); + if (code != JNI_OK) { + return code; + } + + settings_file_specified = (flags_file != NULL); if (IgnoreUnrecognizedVMOptions) { // uncast const to modify the flag args->ignoreUnrecognized *(jboolean*)(&args->ignoreUnrecognized) = true; + java_tool_options_args.get()->ignoreUnrecognized = true; + java_options_args.get()->ignoreUnrecognized = true; } // Parse specified settings file @@ -3672,16 +3744,15 @@ } if (PrintVMOptions) { - for (index = 0; index < args->nOptions; index++) { - const JavaVMOption *option = args->options + index; - if (match_option(option, "-XX:", &tail)) { - logOption(tail); - } - } + print_options(java_tool_options_args.get()); + print_options(args); + print_options(java_options_args.get()); } // Parse JavaVMInitArgs structure passed in, as well as JAVA_TOOL_OPTIONS and _JAVA_OPTIONS - jint result = parse_vm_init_args(args); + jint result = parse_vm_init_args(java_tool_options_args.get(), + java_options_args.get(), args); + if (result != JNI_OK) { return result; }