jint Arguments::parse_each_vm_init_arg()

in src/hotspot/share/runtime/arguments.cpp [2157:2888]


jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, JVMFlagOrigin origin) {
  // For match_option to return remaining or value part of option string
  const char* tail;

  // iterate over arguments
  for (int index = 0; index < args->nOptions; index++) {
    bool is_absolute_path = false;  // for -agentpath vs -agentlib

    const JavaVMOption* option = args->options + index;

    if (!match_option(option, "-Djava.class.path", &tail) &&
        !match_option(option, "-Dsun.java.command", &tail) &&
        !match_option(option, "-Dsun.java.launcher", &tail)) {

        // add all jvm options to the jvm_args string. This string
        // is used later to set the java.vm.args PerfData string constant.
        // the -Djava.class.path and the -Dsun.java.command options are
        // omitted from jvm_args string as each have their own PerfData
        // string constant object.
        build_jvm_args(option->optionString);
    }

    // -verbose:[class/module/gc/jni]
    if (match_option(option, "-verbose", &tail)) {
      if (!strcmp(tail, ":class") || !strcmp(tail, "")) {
        LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(class, load));
        LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(class, unload));
      } else if (!strcmp(tail, ":module")) {
        LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(module, load));
        LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(module, unload));
      } else if (!strcmp(tail, ":gc")) {
        if (_legacyGCLogging.lastFlag == 0) {
          _legacyGCLogging.lastFlag = 1;
        }
      } else if (!strcmp(tail, ":jni")) {
        LogConfiguration::configure_stdout(LogLevel::Debug, true, LOG_TAGS(jni, resolve));
      }
    // -da / -ea / -disableassertions / -enableassertions
    // These accept an optional class/package name separated by a colon, e.g.,
    // -da:java.lang.Thread.
    } else if (match_option(option, user_assertion_options, &tail, true)) {
      bool enable = option->optionString[1] == 'e';     // char after '-' is 'e'
      if (*tail == '\0') {
        JavaAssertions::setUserClassDefault(enable);
      } else {
        assert(*tail == ':', "bogus match by match_option()");
        JavaAssertions::addOption(tail + 1, enable);
      }
    // -dsa / -esa / -disablesystemassertions / -enablesystemassertions
    } else if (match_option(option, system_assertion_options, &tail, false)) {
      bool enable = option->optionString[1] == 'e';     // char after '-' is 'e'
      JavaAssertions::setSystemClassDefault(enable);
    // -bootclasspath:
    } else if (match_option(option, "-Xbootclasspath:", &tail)) {
        jio_fprintf(defaultStream::output_stream(),
          "-Xbootclasspath is no longer a supported option.\n");
        return JNI_EINVAL;
    // -bootclasspath/a:
    } else if (match_option(option, "-Xbootclasspath/a:", &tail)) {
      Arguments::append_sysclasspath(tail);
    // -bootclasspath/p:
    } else if (match_option(option, "-Xbootclasspath/p:", &tail)) {
        jio_fprintf(defaultStream::output_stream(),
          "-Xbootclasspath/p is no longer a supported option.\n");
        return JNI_EINVAL;
    // -Xrun
    } else if (match_option(option, "-Xrun", &tail)) {
      if (tail != nullptr) {
        const char* pos = strchr(tail, ':');
        size_t len = (pos == nullptr) ? strlen(tail) : pos - tail;
        char* name = NEW_C_HEAP_ARRAY(char, len + 1, mtArguments);
        jio_snprintf(name, len + 1, "%s", tail);

        char *options = nullptr;
        if(pos != nullptr) {
          size_t len2 = strlen(pos+1) + 1; // options start after ':'.  Final zero must be copied.
          options = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len2, mtArguments), pos+1, len2);
        }
#if !INCLUDE_JVMTI
        if (strcmp(name, "jdwp") == 0) {
          jio_fprintf(defaultStream::error_stream(),
            "Debugging agents are not supported in this VM\n");
          return JNI_ERR;
        }
#endif // !INCLUDE_JVMTI
        JvmtiAgentList::add_xrun(name, options, false);
        FREE_C_HEAP_ARRAY(char, name);
        FREE_C_HEAP_ARRAY(char, options);
      }
    } else if (match_option(option, "--add-reads=", &tail)) {
      if (!create_numbered_module_property("jdk.module.addreads", tail, addreads_count++)) {
        return JNI_ENOMEM;
      }
    } else if (match_option(option, "--add-exports=", &tail)) {
      if (!create_numbered_module_property("jdk.module.addexports", tail, addexports_count++)) {
        return JNI_ENOMEM;
      }
    } else if (match_option(option, "--add-opens=", &tail)) {
      if (!create_numbered_module_property("jdk.module.addopens", tail, addopens_count++)) {
        return JNI_ENOMEM;
      }
    } else if (match_option(option, "--add-modules=", &tail)) {
      if (!create_numbered_module_property("jdk.module.addmods", tail, _addmods_count++)) {
        return JNI_ENOMEM;
      }
#if INCLUDE_JVMCI
      if (!_jvmci_module_added) {
        const char *jvmci_module = strstr(tail, "jdk.internal.vm.ci");
        if (jvmci_module != nullptr) {
          char before = *(jvmci_module - 1);
          char after  = *(jvmci_module + strlen("jdk.internal.vm.ci"));
          if ((before == '=' || before == ',') && (after == '\0' || after == ',')) {
            FLAG_SET_DEFAULT(EnableJVMCI, true);
            _jvmci_module_added = true;
          }
        }
      }
#endif
    } else if (match_option(option, "--enable-native-access=", &tail)) {
      if (!create_numbered_module_property("jdk.module.enable.native.access", tail, enable_native_access_count++)) {
        return JNI_ENOMEM;
      }
    } else if (match_option(option, "--illegal-native-access=", &tail)) {
      if (!create_module_property("jdk.module.illegal.native.access", tail, InternalProperty)) {
        return JNI_ENOMEM;
      }
    } else if (match_option(option, "--limit-modules=", &tail)) {
      if (!create_module_property("jdk.module.limitmods", tail, InternalProperty)) {
        return JNI_ENOMEM;
      }
    } else if (match_option(option, "--module-path=", &tail)) {
      if (!create_module_property("jdk.module.path", tail, ExternalProperty)) {
        return JNI_ENOMEM;
      }
    } else if (match_option(option, "--upgrade-module-path=", &tail)) {
      if (!create_module_property("jdk.module.upgrade.path", tail, ExternalProperty)) {
        return JNI_ENOMEM;
      }
    } else if (match_option(option, "--patch-module=", &tail)) {
      // --patch-module=<module>=<file>(<pathsep><file>)*
      int res = process_patch_mod_option(tail);
      if (res != JNI_OK) {
        return res;
      }
    } else if (match_option(option, "--enable-final-field-mutation=", &tail)) {
      if (!create_numbered_module_property("jdk.module.enable.final.field.mutation", tail, enable_final_field_mutation++)) {
        return JNI_ENOMEM;
      }
    } else if (match_option(option, "--illegal-final-field-mutation=", &tail)) {
      if (strcmp(tail, "allow") == 0 || strcmp(tail, "warn") == 0 || strcmp(tail, "debug") == 0 || strcmp(tail, "deny") == 0) {
        PropertyList_unique_add(&_system_properties, "jdk.module.illegal.final.field.mutation", tail,
                                AddProperty, WriteableProperty, InternalProperty);
      } else {
        jio_fprintf(defaultStream::error_stream(),
                    "Value specified to --illegal-final-field-mutation not recognized: '%s'\n", tail);
        return JNI_ERR;
      }
    } else if (match_option(option, "--sun-misc-unsafe-memory-access=", &tail)) {
      if (strcmp(tail, "allow") == 0 || strcmp(tail, "warn") == 0 || strcmp(tail, "debug") == 0 || strcmp(tail, "deny") == 0) {
        PropertyList_unique_add(&_system_properties, "sun.misc.unsafe.memory.access", tail,
                                AddProperty, WriteableProperty, InternalProperty);
      } else {
        jio_fprintf(defaultStream::error_stream(),
                    "Value specified to --sun-misc-unsafe-memory-access not recognized: '%s'\n", tail);
        return JNI_ERR;
      }
    } else if (match_option(option, "--illegal-access=", &tail)) {
      char version[256];
      JDK_Version::jdk(17).to_string(version, sizeof(version));
      warning("Ignoring option %s; support was removed in %s", option->optionString, version);
    // -agentlib and -agentpath
    } else if (match_option(option, "-agentlib:", &tail) ||
          (is_absolute_path = match_option(option, "-agentpath:", &tail))) {
      if(tail != nullptr) {
        const char* pos = strchr(tail, '=');
        char* name;
        if (pos == nullptr) {
          name = os::strdup_check_oom(tail, mtArguments);
        } else {
          size_t len = pos - tail;
          name = NEW_C_HEAP_ARRAY(char, len + 1, mtArguments);
          memcpy(name, tail, len);
          name[len] = '\0';
        }

        char *options = nullptr;
        if(pos != nullptr) {
          options = os::strdup_check_oom(pos + 1, mtArguments);
        }
#if !INCLUDE_JVMTI
        if (valid_jdwp_agent(name, is_absolute_path)) {
          jio_fprintf(defaultStream::error_stream(),
            "Debugging agents are not supported in this VM\n");
          return JNI_ERR;
        }
#elif INCLUDE_CDS
        if (valid_jdwp_agent(name, is_absolute_path)) {
          _has_jdwp_agent = true;
        }
#endif // !INCLUDE_JVMTI
        JvmtiAgentList::add(name, options, is_absolute_path);
        os::free(name);
        os::free(options);
      }
    // -javaagent
    } else if (match_option(option, "-javaagent:", &tail)) {
#if !INCLUDE_JVMTI
      jio_fprintf(defaultStream::error_stream(),
        "Instrumentation agents are not supported in this VM\n");
      return JNI_ERR;
#else
      if (tail != nullptr) {
        size_t length = strlen(tail) + 1;
        char *options = NEW_C_HEAP_ARRAY(char, length, mtArguments);
        jio_snprintf(options, length, "%s", tail);
        JvmtiAgentList::add("instrument", options, false);
        FREE_C_HEAP_ARRAY(char, options);

        // java agents need module java.instrument
        if (!create_numbered_module_property("jdk.module.addmods", "java.instrument", _addmods_count++)) {
          return JNI_ENOMEM;
        }
      }
#endif // !INCLUDE_JVMTI
    // --enable_preview
    } else if (match_option(option, "--enable-preview")) {
      set_enable_preview();
    // -Xnoclassgc
    } else if (match_option(option, "-Xnoclassgc")) {
      if (FLAG_SET_CMDLINE(ClassUnloading, false) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    // -Xbatch
    } else if (match_option(option, "-Xbatch")) {
      if (FLAG_SET_CMDLINE(BackgroundCompilation, false) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    // -Xmn for compatibility with other JVM vendors
    } else if (match_option(option, "-Xmn", &tail)) {
      julong long_initial_young_size = 0;
      ArgsRange errcode = parse_memory_size(tail, &long_initial_young_size, 1);
      if (errcode != arg_in_range) {
        jio_fprintf(defaultStream::error_stream(),
                    "Invalid initial young generation size: %s\n", option->optionString);
        describe_range_error(errcode);
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(MaxNewSize, (size_t)long_initial_young_size) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(NewSize, (size_t)long_initial_young_size) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    // -Xms
    } else if (match_option(option, "-Xms", &tail)) {
      julong size = 0;
      // an initial heap size of 0 means automatically determine
      ArgsRange errcode = parse_memory_size(tail, &size, 0);
      if (errcode != arg_in_range) {
        jio_fprintf(defaultStream::error_stream(),
                    "Invalid initial heap size: %s\n", option->optionString);
        describe_range_error(errcode);
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(MinHeapSize, (size_t)size) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(InitialHeapSize, (size_t)size) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    // -Xmx
    } else if (match_option(option, "-Xmx", &tail) || match_option(option, "-XX:MaxHeapSize=", &tail)) {
      julong long_max_heap_size = 0;
      ArgsRange errcode = parse_memory_size(tail, &long_max_heap_size, 1);
      if (errcode != arg_in_range) {
        jio_fprintf(defaultStream::error_stream(),
                    "Invalid maximum heap size: %s\n", option->optionString);
        describe_range_error(errcode);
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(MaxHeapSize, (size_t)long_max_heap_size) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    // Xmaxf
    } else if (match_option(option, "-Xmaxf", &tail)) {
      char* err;
      double dmaxf = strtod(tail, &err);
      if (*err != '\0' || *tail == '\0') {
        jio_fprintf(defaultStream::error_stream(),
                    "Bad max heap free ratio: %s\n",
                    option->optionString);
        return JNI_EINVAL;
      }
      if (dmaxf < 0.0 || dmaxf > 1.0) {
        jio_fprintf(defaultStream::error_stream(),
                    "-Xmaxf value (%s) is outside the allowed range [ 0.0 ... 1.0 ]\n",
                    option->optionString);
        return JNI_EINVAL;
      }
      const uintx umaxf = (uintx)(dmaxf * 100);
      if (MinHeapFreeRatio > umaxf) {
        jio_fprintf(defaultStream::error_stream(),
                    "-Xmaxf value (%s) must be greater than or equal to the implicit -Xminf value (%.2f)\n",
                    tail, MinHeapFreeRatio / 100.0f);
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(MaxHeapFreeRatio, umaxf) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    // Xminf
    } else if (match_option(option, "-Xminf", &tail)) {
      char* err;
      double dminf = strtod(tail, &err);
      if (*err != '\0' || *tail == '\0') {
        jio_fprintf(defaultStream::error_stream(),
                    "Bad min heap free ratio: %s\n",
                    option->optionString);
        return JNI_EINVAL;
      }
      if (dminf < 0.0 || dminf > 1.0) {
        jio_fprintf(defaultStream::error_stream(),
                    "-Xminf value (%s) is outside the allowed range [ 0.0 ... 1.0 ]\n",
                    tail);
        return JNI_EINVAL;
      }
      const uintx uminf = (uintx)(dminf * 100);
      if (MaxHeapFreeRatio < uminf) {
        jio_fprintf(defaultStream::error_stream(),
                    "-Xminf value (%s) must be less than or equal to the implicit -Xmaxf value (%.2f)\n",
                    tail, MaxHeapFreeRatio / 100.0f);
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(MinHeapFreeRatio, uminf) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    // -Xss
    } else if (match_option(option, "-Xss", &tail)) {
      intx value = 0;
      jint err = parse_xss(option, tail, &value);
      if (err != JNI_OK) {
        return err;
      }
      if (FLAG_SET_CMDLINE(ThreadStackSize, value) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    } else if (match_option(option, "-Xmaxjitcodesize", &tail) ||
               match_option(option, "-XX:ReservedCodeCacheSize=", &tail)) {
      if (match_option(option, "-Xmaxjitcodesize", &tail)) {
        warning("Option -Xmaxjitcodesize was deprecated in JDK 26 and will likely be removed in a future release.");
      }
      julong long_ReservedCodeCacheSize = 0;

      ArgsRange errcode = parse_memory_size(tail, &long_ReservedCodeCacheSize, 1);
      if (errcode != arg_in_range) {
        jio_fprintf(defaultStream::error_stream(),
                    "Invalid maximum code cache size: %s.\n", option->optionString);
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(ReservedCodeCacheSize, (size_t)long_ReservedCodeCacheSize) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    // -green
    } else if (match_option(option, "-green")) {
      jio_fprintf(defaultStream::error_stream(),
                  "Green threads support not available\n");
          return JNI_EINVAL;
    // -native
    } else if (match_option(option, "-native")) {
          // HotSpot always uses native threads, ignore silently for compatibility
    // -Xrs
    } else if (match_option(option, "-Xrs")) {
          // Classic/EVM option, new functionality
      if (FLAG_SET_CMDLINE(ReduceSignalUsage, true) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
      // -Xprof
    } else if (match_option(option, "-Xprof")) {
      char version[256];
      // Obsolete in JDK 10
      JDK_Version::jdk(10).to_string(version, sizeof(version));
      warning("Ignoring option %s; support was removed in %s", option->optionString, version);
    // -Xinternalversion
    } else if (match_option(option, "-Xinternalversion")) {
      jio_fprintf(defaultStream::output_stream(), "%s\n",
                  VM_Version::internal_vm_info_string());
      vm_exit(0);
#ifndef PRODUCT
    // -Xprintflags
    } else if (match_option(option, "-Xprintflags")) {
      JVMFlag::printFlags(tty, false);
      vm_exit(0);
#endif
    // -D
    } else if (match_option(option, "-D", &tail)) {
      const char* value;
      if (match_option(option, "-Djava.endorsed.dirs=", &value) &&
            *value!= '\0' && strcmp(value, "\"\"") != 0) {
        // abort if -Djava.endorsed.dirs is set
        jio_fprintf(defaultStream::output_stream(),
          "-Djava.endorsed.dirs=%s is not supported. Endorsed standards and standalone APIs\n"
          "in modular form will be supported via the concept of upgradeable modules.\n", value);
        return JNI_EINVAL;
      }
      if (match_option(option, "-Djava.ext.dirs=", &value) &&
            *value != '\0' && strcmp(value, "\"\"") != 0) {
        // abort if -Djava.ext.dirs is set
        jio_fprintf(defaultStream::output_stream(),
          "-Djava.ext.dirs=%s is not supported.  Use -classpath instead.\n", value);
        return JNI_EINVAL;
      }
      // 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;
      }
      if (!add_property(tail)) {
        return JNI_ENOMEM;
      }
      // Out of the box management support
      if (match_option(option, "-Dcom.sun.management", &tail)) {
#if INCLUDE_MANAGEMENT
        if (FLAG_SET_CMDLINE(ManagementServer, true) != JVMFlag::SUCCESS) {
          return JNI_EINVAL;
        }
        // management agent in module jdk.management.agent
        if (!create_numbered_module_property("jdk.module.addmods", "jdk.management.agent", _addmods_count++)) {
          return JNI_ENOMEM;
        }
#else
        jio_fprintf(defaultStream::output_stream(),
          "-Dcom.sun.management is not supported in this VM.\n");
        return JNI_ERR;
#endif
      }
    // -Xint
    } else if (match_option(option, "-Xint")) {
          set_mode_flags(_int);
          mode_flag_cmd_line = true;
    // -Xmixed
    } else if (match_option(option, "-Xmixed")) {
          set_mode_flags(_mixed);
          mode_flag_cmd_line = true;
    // -Xcomp
    } else if (match_option(option, "-Xcomp")) {
      // for testing the compiler; turn off all flags that inhibit compilation
          set_mode_flags(_comp);
          mode_flag_cmd_line = true;
    // -Xshare:dump
    } else if (match_option(option, "-Xshare:dump")) {
      CDSConfig::enable_dumping_static_archive();
      CDSConfig::set_old_cds_flags_used();
    // -Xshare:on
    } else if (match_option(option, "-Xshare:on")) {
      UseSharedSpaces = true;
      RequireSharedSpaces = true;
      CDSConfig::set_old_cds_flags_used();
    // -Xshare:auto || -XX:ArchiveClassesAtExit=<archive file>
    } else if (match_option(option, "-Xshare:auto")) {
      UseSharedSpaces = true;
      RequireSharedSpaces = false;
      xshare_auto_cmd_line = true;
      CDSConfig::set_old_cds_flags_used();
    // -Xshare:off
    } else if (match_option(option, "-Xshare:off")) {
      UseSharedSpaces = false;
      RequireSharedSpaces = false;
      CDSConfig::set_old_cds_flags_used();
    // -Xverify
    } else if (match_option(option, "-Xverify", &tail)) {
      if (strcmp(tail, ":all") == 0 || strcmp(tail, "") == 0) {
        if (FLAG_SET_CMDLINE(BytecodeVerificationLocal, true) != JVMFlag::SUCCESS) {
          return JNI_EINVAL;
        }
        if (FLAG_SET_CMDLINE(BytecodeVerificationRemote, true) != JVMFlag::SUCCESS) {
          return JNI_EINVAL;
        }
      } else if (strcmp(tail, ":remote") == 0) {
        if (FLAG_SET_CMDLINE(BytecodeVerificationLocal, false) != JVMFlag::SUCCESS) {
          return JNI_EINVAL;
        }
        if (FLAG_SET_CMDLINE(BytecodeVerificationRemote, true) != JVMFlag::SUCCESS) {
          return JNI_EINVAL;
        }
      } else if (strcmp(tail, ":none") == 0) {
        if (FLAG_SET_CMDLINE(BytecodeVerificationLocal, false) != JVMFlag::SUCCESS) {
          return JNI_EINVAL;
        }
        if (FLAG_SET_CMDLINE(BytecodeVerificationRemote, false) != JVMFlag::SUCCESS) {
          return JNI_EINVAL;
        }
        warning("Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.");
      } else if (is_bad_option(option, args->ignoreUnrecognized, "verification")) {
        return JNI_EINVAL;
      }
    // -Xdebug
    } else if (match_option(option, "-Xdebug")) {
      warning("Option -Xdebug was deprecated in JDK 22 and will likely be removed in a future release.");
    } else if (match_option(option, "-Xloggc:", &tail)) {
      // Deprecated flag to redirect GC output to a file. -Xloggc:<filename>
      log_warning(gc)("-Xloggc is deprecated. Will use -Xlog:gc:%s instead.", tail);
      _legacyGCLogging.lastFlag = 2;
      _legacyGCLogging.file = os::strdup_check_oom(tail);
    } else if (match_option(option, "-Xlog", &tail)) {
      bool ret = false;
      if (strcmp(tail, ":help") == 0) {
        fileStream stream(defaultStream::output_stream());
        LogConfiguration::print_command_line_help(&stream);
        vm_exit(0);
      } else if (strcmp(tail, ":disable") == 0) {
        LogConfiguration::disable_logging();
        ret = true;
      } else if (strncmp(tail, ":async", strlen(":async")) == 0) {
        const char* async_tail = tail + strlen(":async");
        ret = LogConfiguration::parse_async_argument(async_tail);
      } else if (*tail == '\0') {
        ret = LogConfiguration::parse_command_line_arguments();
        assert(ret, "-Xlog without arguments should never fail to parse");
      } else if (*tail == ':') {
        ret = LogConfiguration::parse_command_line_arguments(tail + 1);
      }
      if (ret == false) {
        jio_fprintf(defaultStream::error_stream(),
                    "Invalid -Xlog option '-Xlog%s', see error log for details.\n",
                    tail);
        return JNI_EINVAL;
      }
    // JNI hooks
    } else if (match_option(option, "-Xcheck", &tail)) {
      if (!strcmp(tail, ":jni")) {
#if !INCLUDE_JNI_CHECK
        warning("JNI CHECKING is not supported in this VM");
#else
        CheckJNICalls = true;
#endif // INCLUDE_JNI_CHECK
      } else if (is_bad_option(option, args->ignoreUnrecognized,
                                     "check")) {
        return JNI_EINVAL;
      }
    } else if (match_option(option, "vfprintf")) {
      _vfprintf_hook = CAST_TO_FN_PTR(vfprintf_hook_t, option->extraInfo);
    } else if (match_option(option, "exit")) {
      _exit_hook = CAST_TO_FN_PTR(exit_hook_t, option->extraInfo);
    } else if (match_option(option, "abort")) {
      _abort_hook = CAST_TO_FN_PTR(abort_hook_t, option->extraInfo);
    // Need to keep consistency of MaxTenuringThreshold and AlwaysTenure/NeverTenure;
    // and the last option wins.
    } else if (match_option(option, "-XX:+NeverTenure")) {
      if (FLAG_SET_CMDLINE(NeverTenure, true) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(AlwaysTenure, false) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(MaxTenuringThreshold, markWord::max_age + 1) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    } else if (match_option(option, "-XX:+AlwaysTenure")) {
      if (FLAG_SET_CMDLINE(NeverTenure, false) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(AlwaysTenure, true) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(MaxTenuringThreshold, 0) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    } else if (match_option(option, "-XX:MaxTenuringThreshold=", &tail)) {
      uint max_tenuring_thresh = 0;
      if (!parse_uint(tail, &max_tenuring_thresh, 0)) {
        jio_fprintf(defaultStream::error_stream(),
                    "Improperly specified VM option \'MaxTenuringThreshold=%s\'\n", tail);
        return JNI_EINVAL;
      }

      if (FLAG_SET_CMDLINE(MaxTenuringThreshold, max_tenuring_thresh) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }

      if (MaxTenuringThreshold == 0) {
        if (FLAG_SET_CMDLINE(NeverTenure, false) != JVMFlag::SUCCESS) {
          return JNI_EINVAL;
        }
        if (FLAG_SET_CMDLINE(AlwaysTenure, true) != JVMFlag::SUCCESS) {
          return JNI_EINVAL;
        }
      } else {
        if (FLAG_SET_CMDLINE(NeverTenure, false) != JVMFlag::SUCCESS) {
          return JNI_EINVAL;
        }
        if (FLAG_SET_CMDLINE(AlwaysTenure, false) != JVMFlag::SUCCESS) {
          return JNI_EINVAL;
        }
      }
    } else if (match_option(option, "-XX:+DisplayVMOutputToStderr")) {
      if (FLAG_SET_CMDLINE(DisplayVMOutputToStdout, false) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(DisplayVMOutputToStderr, true) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    } else if (match_option(option, "-XX:+DisplayVMOutputToStdout")) {
      if (FLAG_SET_CMDLINE(DisplayVMOutputToStderr, false) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(DisplayVMOutputToStdout, true) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    } else if (match_option(option, "-XX:+ErrorFileToStderr")) {
      if (FLAG_SET_CMDLINE(ErrorFileToStdout, false) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(ErrorFileToStderr, true) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    } else if (match_option(option, "-XX:+ErrorFileToStdout")) {
      if (FLAG_SET_CMDLINE(ErrorFileToStderr, false) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
      if (FLAG_SET_CMDLINE(ErrorFileToStdout, true) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
    } else if (match_option(option, "--finalization=", &tail)) {
      if (strcmp(tail, "enabled") == 0) {
        InstanceKlass::set_finalization_enabled(true);
      } else if (strcmp(tail, "disabled") == 0) {
        InstanceKlass::set_finalization_enabled(false);
      } else {
        jio_fprintf(defaultStream::error_stream(),
                    "Invalid finalization value '%s', must be 'disabled' or 'enabled'.\n",
                    tail);
        return JNI_EINVAL;
      }
#if !defined(DTRACE_ENABLED)
    } else if (match_option(option, "-XX:+DTraceMethodProbes")) {
      jio_fprintf(defaultStream::error_stream(),
                  "DTraceMethodProbes flag is not applicable for this configuration\n");
      return JNI_EINVAL;
    } else if (match_option(option, "-XX:+DTraceAllocProbes")) {
      jio_fprintf(defaultStream::error_stream(),
                  "DTraceAllocProbes flag is not applicable for this configuration\n");
      return JNI_EINVAL;
    } else if (match_option(option, "-XX:+DTraceMonitorProbes")) {
      jio_fprintf(defaultStream::error_stream(),
                  "DTraceMonitorProbes flag is not applicable for this configuration\n");
      return JNI_EINVAL;
#endif // !defined(DTRACE_ENABLED)
#ifdef ASSERT
    } else if (match_option(option, "-XX:+FullGCALot")) {
      if (FLAG_SET_CMDLINE(FullGCALot, true) != JVMFlag::SUCCESS) {
        return JNI_EINVAL;
      }
#endif
#if !INCLUDE_MANAGEMENT
    } else if (match_option(option, "-XX:+ManagementServer")) {
        jio_fprintf(defaultStream::error_stream(),
          "ManagementServer is not supported in this VM.\n");
        return JNI_ERR;
#endif // INCLUDE_MANAGEMENT
#if INCLUDE_JVMCI
    } else if (match_option(option, "-XX:-EnableJVMCIProduct") || match_option(option, "-XX:-UseGraalJIT")) {
      if (EnableJVMCIProduct) {
        jio_fprintf(defaultStream::error_stream(),
                  "-XX:-EnableJVMCIProduct or -XX:-UseGraalJIT cannot come after -XX:+EnableJVMCIProduct or -XX:+UseGraalJIT\n");
        return JNI_EINVAL;
      }
    } else if (match_option(option, "-XX:+EnableJVMCIProduct") || match_option(option, "-XX:+UseGraalJIT")) {
      bool use_graal_jit = match_option(option, "-XX:+UseGraalJIT");
      if (use_graal_jit) {
        const char* jvmci_compiler = get_property("jvmci.Compiler");
        if (jvmci_compiler != nullptr) {
          if (strncmp(jvmci_compiler, "graal", strlen("graal")) != 0) {
            jio_fprintf(defaultStream::error_stream(),
              "Value of jvmci.Compiler incompatible with +UseGraalJIT: %s\n", jvmci_compiler);
            return JNI_ERR;
          }
        } else if (!add_property("jvmci.Compiler=graal")) {
            return JNI_ENOMEM;
        }
      }

      // Just continue, since "-XX:+EnableJVMCIProduct" or "-XX:+UseGraalJIT" has been specified before
      if (EnableJVMCIProduct) {
        continue;
      }
      JVMFlag *jvmciFlag = JVMFlag::find_flag("EnableJVMCIProduct");
      // Allow this flag if it has been unlocked.
      if (jvmciFlag != nullptr && jvmciFlag->is_unlocked()) {
        if (!JVMCIGlobals::enable_jvmci_product_mode(origin, use_graal_jit)) {
          jio_fprintf(defaultStream::error_stream(),
            "Unable to enable JVMCI in product mode\n");
          return JNI_ERR;
        }
      }
      // The flag was locked so process normally to report that error
      else if (!process_argument(use_graal_jit ? "UseGraalJIT" : "EnableJVMCIProduct", args->ignoreUnrecognized, origin)) {
        return JNI_EINVAL;
      }
#endif // INCLUDE_JVMCI
#if INCLUDE_JFR
    } else if (match_jfr_option(&option)) {
      return JNI_EINVAL;
#endif
    } else if (match_option(option, "-XX:", &tail)) { // -XX:xxxx
      // Skip -XX:Flags= and -XX:VMOptionsFile= since those cases have
      // already been handled
      if ((strncmp(tail, "Flags=", strlen("Flags=")) != 0) &&
          (strncmp(tail, "VMOptionsFile=", strlen("VMOptionsFile=")) != 0)) {
        if (!process_argument(tail, args->ignoreUnrecognized, origin)) {
          return JNI_EINVAL;
        }
      }
    // Unknown option
    } else if (is_bad_option(option, args->ignoreUnrecognized)) {
      return JNI_ERR;
    }
  }

  // PrintSharedArchiveAndExit will turn on
  //   -Xshare:on
  //   -Xlog:class+path=info
  if (PrintSharedArchiveAndExit) {
    UseSharedSpaces = true;
    RequireSharedSpaces = true;
    LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(class, path));
  }

  fix_appclasspath();

  return JNI_OK;
}