82
83 /*
84 * Entries for splash screen environment variables.
85 * putenv is performed in SelectVersion. We need
86 * them in memory until UnsetEnv, so they are made static
87 * global instead of auto local.
88 */
89 static char* splash_file_entry = NULL;
90 static char* splash_jar_entry = NULL;
91
92 /*
93 * List of VM options to be specified when the VM is created.
94 */
95 static JavaVMOption *options;
96 static int numOptions, maxOptions;
97
98 /*
99 * Prototypes for functions internal to launcher.
100 */
101 static void SetClassPath(const char *s);
102 static void SetModulePath(const char *s);
103 static void SetUpgradeModulePath(const char *s);
104 static void SetMainModule(const char *s);
105 static void SetAddModulesProp(const char *mods);
106 static void SetLimitModulesProp(const char *mods);
107 static void SetAddReadsProp(const jint n, const char *s);
108 static void SetAddExportsProp(const jint n, const char *s);
109 static void SetPatchProp(const jint n, const char *s);
110 static void SelectVersion(int argc, char **argv, char **main_class);
111 static void SetJvmEnvironment(int argc, char **argv);
112 static jboolean IsWhiteSpaceOptionArgument(const char* name);
113 static jboolean ParseArguments(int *pargc, char ***pargv,
114 int *pmode, char **pwhat,
115 int *pret, const char *jrepath);
116 static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
117 InvocationFunctions *ifn);
118 static jstring NewPlatformString(JNIEnv *env, char *s);
119 static jclass LoadMainClass(JNIEnv *env, int mode, char *name);
120 static jclass GetApplicationClass(JNIEnv *env);
121
122 static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv);
123 static jboolean AddApplicationOptions(int cpathc, const char **cpathv);
124 static void SetApplicationClassPath(const char**);
125
126 static void PrintJavaVersion(JNIEnv *env, jboolean extraLF);
127 static void PrintUsage(JNIEnv* env, jboolean doXUsage);
128 static void ShowSettings(JNIEnv* env, char *optString);
129 static void ListModules(JNIEnv* env, char *optString);
130
131 static void SetPaths(int argc, char **argv);
132
133 static void DumpState();
134 static jboolean RemovableOption(char *option);
135
136 /* Maximum supported entries from jvm.cfg. */
137 #define INIT_MAX_KNOWN_VMS 10
138
139 /* Values for vmdesc.flag */
140 enum vmdesc_flag {
141 VM_UNKNOWN = -1,
142 VM_KNOWN,
143 VM_ALIASED_TO,
144 VM_WARN,
145 VM_ERROR,
146 VM_IF_SERVER_CLASS,
147 VM_IGNORE
148 };
149
150 struct vmdesc {
151 char *name;
152 int flag;
153 char *alias;
154 char *server_class;
155 };
156 static struct vmdesc *knownVMs = NULL;
157 static int knownVMsCount = 0;
158 static int knownVMsLimit = 0;
159
160 static void GrowKnownVMs(int minimum);
161 static int KnownVMIndex(const char* name);
162 static void FreeKnownVMs();
163 static jboolean IsWildCardEnabled();
164
165 #define ARG_CHECK(AC_arg_count, AC_failure_message, AC_questionable_arg) \
166 do { \
167 if (AC_arg_count < 1) { \
168 JLI_ReportErrorMessage(AC_failure_message, AC_questionable_arg); \
169 printUsage = JNI_TRUE; \
170 *pret = 1; \
171 return JNI_TRUE; \
172 } \
173 } while (JNI_FALSE)
174
175 /*
176 * Running Java code in primordial thread caused many problems. We will
177 * create a new thread to invoke JVM. See 6316197 for more information.
178 */
179 static jlong threadStackSize = 0; /* stack size of the new thread */
180 static jlong maxHeapSize = 0; /* max heap size */
181 static jlong initialHeapSize = 0; /* inital heap size */
182
183 /*
184 * A minimum -Xss stack size suitable for all platforms.
494 * is not required. The main method is invoked here so that extraneous java
495 * stacks are not in the application stack trace.
496 */
497 mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
498 "([Ljava/lang/String;)V");
499 CHECK_EXCEPTION_NULL_LEAVE(mainID);
500
501 /* Invoke main method. */
502 (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
503
504 /*
505 * The launcher's exit code (in the absence of calls to
506 * System.exit) will be non-zero if main threw an exception.
507 */
508 ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
509
510 LEAVE();
511 }
512
513 /*
514 * Test if the given option name has a whitespace separated argument.
515 */
516 jboolean
517 IsWhiteSpaceOptionArgument(const char* name) {
518 return JLI_StrCmp(name, "-classpath") == 0 ||
519 JLI_StrCmp(name, "-cp") == 0 ||
520 JLI_StrCmp(name, "-modulepath") == 0 ||
521 JLI_StrCmp(name, "-mp") == 0 ||
522 JLI_StrCmp(name, "-upgrademodulepath") == 0 ||
523 JLI_StrCmp(name, "-addmods") == 0 ||
524 JLI_StrCmp(name, "-limitmods") == 0;
525 }
526
527 /*
528 * Checks the command line options to find which JVM type was
529 * specified. If no command line option was given for the JVM type,
530 * the default type is used. The environment variable
531 * JDK_ALTERNATE_VM and the command line option -XXaltjvm= are also
532 * checked as ways of specifying which JVM type to invoke.
533 */
534 char *
535 CheckJvmType(int *pargc, char ***argv, jboolean speculative) {
536 int i, argi;
537 int argc;
538 char **newArgv;
539 int newArgvIdx = 0;
540 int isVMType;
541 int jvmidx = -1;
542 char *jvmtype = getenv("JDK_ALTERNATE_VM");
543
544 argc = *pargc;
545
546 /* To make things simpler we always copy the argv array */
547 newArgv = JLI_MemAlloc((argc + 1) * sizeof(char *));
548
549 /* The program name is always present */
550 newArgv[newArgvIdx++] = (*argv)[0];
551
552 for (argi = 1; argi < argc; argi++) {
553 char *arg = (*argv)[argi];
554 isVMType = 0;
555
556 if (IsJavaArgs()) {
557 if (arg[0] != '-') {
558 newArgv[newArgvIdx++] = arg;
559 continue;
560 }
561 } else {
562 if (IsWhiteSpaceOptionArgument(arg)) {
563 newArgv[newArgvIdx++] = arg;
564 argi++;
565 if (argi < argc) {
566 newArgv[newArgvIdx++] = (*argv)[argi];
567 }
568 continue;
569 }
570 if (arg[0] != '-') break;
571 }
572
573 /* Did the user pass an explicit VM type? */
574 i = KnownVMIndex(arg);
575 if (i >= 0) {
576 jvmtype = knownVMs[jvmidx = i].name + 1; /* skip the - */
577 isVMType = 1;
578 *pargc = *pargc - 1;
579 }
580
581 /* Did the user specify an "alternate" VM? */
582 else if (JLI_StrCCmp(arg, "-XXaltjvm=") == 0 || JLI_StrCCmp(arg, "-J-XXaltjvm=") == 0) {
684 * leaving the arg list intact. The first use is for the JVM flag
685 * -XX:NativeMemoryTracking=value.
686 */
687 static void
688 SetJvmEnvironment(int argc, char **argv) {
689
690 static const char* NMT_Env_Name = "NMT_LEVEL_";
691 int i;
692 for (i = 0; i < argc; i++) {
693 char *arg = argv[i];
694 /*
695 * Since this must be a VM flag we stop processing once we see
696 * an argument the launcher would not have processed beyond (such
697 * as -version or -h), or an argument that indicates the following
698 * arguments are for the application (i.e. the main class name, or
699 * the -jar argument).
700 */
701 if (i > 0) {
702 char *prev = argv[i - 1];
703 // skip non-dash arg preceded by class path specifiers
704 if (*arg != '-' && IsWhiteSpaceOptionArgument(prev)) {
705 continue;
706 }
707
708 if (*arg != '-'
709 || JLI_StrCmp(arg, "-version") == 0
710 || JLI_StrCmp(arg, "-fullversion") == 0
711 || JLI_StrCmp(arg, "-help") == 0
712 || JLI_StrCmp(arg, "-?") == 0
713 || JLI_StrCmp(arg, "-jar") == 0
714 || JLI_StrCmp(arg, "-X") == 0) {
715 return;
716 }
717 }
718 /*
719 * The following case checks for "-XX:NativeMemoryTracking=value".
720 * If value is non null, an environmental variable set to this value
721 * will be created to be used by the JVM.
722 * The argument is passed to the JVM, which will check validity.
723 * The JVM is responsible for removing the env variable.
724 */
725 if (JLI_StrCCmp(arg, "-XX:NativeMemoryTracking=") == 0) {
726 int retval;
727 // get what follows this parameter, include "="
728 size_t pnlen = JLI_StrLen("-XX:NativeMemoryTracking=");
729 if (JLI_StrLen(arg) > pnlen) {
730 char* value = arg + pnlen;
731 size_t pbuflen = pnlen + JLI_StrLen(value) + 10; // 10 max pid digits
865 * we might just get one, in which case we simply ignore it, and let the
866 * caller deal with it
867 */
868 if (s == NULL)
869 return;
870 s = JLI_WildcardExpandClasspath(s);
871 if (sizeof(format) - 2 + JLI_StrLen(s) < JLI_StrLen(s))
872 // s is became corrupted after expanding wildcards
873 return;
874 def = JLI_MemAlloc(sizeof(format)
875 - 2 /* strlen("%s") */
876 + JLI_StrLen(s));
877 sprintf(def, format, s);
878 AddOption(def, NULL);
879 if (s != orig)
880 JLI_MemFree((char *) s);
881 _have_classpath = JNI_TRUE;
882 }
883
884 static void
885 SetModulePath(const char *s)
886 {
887 char *def;
888 const char *orig = s;
889 static const char format[] = "-Djdk.module.path=%s";
890 if (s == NULL)
891 return;
892 s = JLI_WildcardExpandClasspath(s);
893 def = JLI_MemAlloc(sizeof(format)
894 - 2 /* strlen("%s") */
895 + JLI_StrLen(s));
896 sprintf(def, format, s);
897 AddOption(def, NULL);
898 if (s != orig)
899 JLI_MemFree((char *) s);
900 }
901
902 static void
903 SetUpgradeModulePath(const char *s)
904 {
905 char *def;
906 const char *orig = s;
907 static const char format[] = "-Djdk.upgrade.module.path=%s";
908 if (s == NULL)
909 return;
910 s = JLI_WildcardExpandClasspath(s);
911 def = JLI_MemAlloc(sizeof(format)
912 - 2 /* strlen("%s") */
913 + JLI_StrLen(s));
914 sprintf(def, format, s);
915 AddOption(def, NULL);
916 if (s != orig)
917 JLI_MemFree((char *) s);
918 }
919
920 static void
921 SetMainModule(const char *s)
922 {
923 static const char format[] = "-Djdk.module.main=%s";
924 char* slash = JLI_StrChr(s, '/');
925 size_t s_len, def_len;
926 char *def;
927
928 /* value may be <module> or <module>/<mainclass> */
929 if (slash == NULL) {
930 s_len = JLI_StrLen(s);
931 } else {
932 s_len = (size_t) (slash - s);
933 }
934 def_len = sizeof(format)
935 - 2 /* strlen("%s") */
936 + s_len;
937 def = JLI_MemAlloc(def_len);
938 JLI_Snprintf(def, def_len, format, s);
939 AddOption(def, NULL);
940 }
941
942 static void
943 SetAddModulesProp(const char *mods) {
944 size_t buflen = JLI_StrLen(mods) + 40;
945 char *prop = (char *)JLI_MemAlloc(buflen);
946 JLI_Snprintf(prop, buflen, "-Djdk.launcher.addmods=%s", mods);
947 AddOption(prop, NULL);
948 }
949
950 static void
951 SetLimitModulesProp(const char *mods) {
952 size_t buflen = JLI_StrLen(mods) + 40;
953 char *prop = (char *)JLI_MemAlloc(buflen);
954 JLI_Snprintf(prop, buflen, "-Djdk.launcher.limitmods=%s", mods);
955 AddOption(prop, NULL);
956 }
957
958 static void
959 SetAddReadsProp(const jint n, const char *s) {
960 size_t buflen = JLI_StrLen(s) + 40;
961 char *prop = (char *)JLI_MemAlloc(buflen);
962 JLI_Snprintf(prop, buflen, "-Djdk.launcher.addreads.%d=%s", n, s);
963 AddOption(prop, NULL);
964 }
965
966 static void
967 SetAddExportsProp(const jint n, const char *s) {
968 size_t buflen = JLI_StrLen(s) + 40;
969 char *prop = (char *)JLI_MemAlloc(buflen);
970 JLI_Snprintf(prop, buflen, "-Djdk.launcher.addexports.%d=%s", n, s);
971 AddOption(prop, NULL);
972 }
973
974 static void
975 SetPatchProp(const jint n, const char *s) {
976 size_t buflen = JLI_StrLen(s) + 40;
977 char *prop = (char *)JLI_MemAlloc(buflen);
978 JLI_Snprintf(prop, buflen, "-Djdk.launcher.patch.%d=%s", n, s);
979 AddOption(prop, NULL);
980 }
981
982 /*
983 * The SelectVersion() routine ensures that an appropriate version of
984 * the JRE is running. The specification for the appropriate version
985 * is obtained from either the manifest of a jar file (preferred) or
986 * from command line options.
987 * The routine also parses splash screen command line options and
988 * passes on their values in private environment variables.
989 */
990 static void
991 SelectVersion(int argc, char **argv, char **main_class)
992 {
993 char *arg;
994 char *operand;
995 char *version = NULL;
996 char *jre = NULL;
997 int jarflag = 0;
998 int headlessflag = 0;
999 int restrict_search = -1; /* -1 implies not known */
1000 manifest_info info;
1001 char env_entry[MAXNAMELEN + 24] = ENV_ENTRY "=";
1002 char *splash_file_name = NULL;
1003 char *splash_jar_name = NULL;
1004 char *env_in;
1005 int res;
1006
1007 /*
1008 * If the version has already been selected, set *main_class
1009 * with the value passed through the environment (if any) and
1010 * simply return.
1011 */
1012
1013 /*
1014 * This environmental variable can be set by mJRE capable JREs
1015 * [ 1.5 thru 1.8 ]. All other aspects of mJRE processing have been
1016 * stripped by those JREs. This environmental variable allows 1.9+
1017 * JREs to be started by these mJRE capable JREs.
1018 * Note that mJRE directives in the jar manifest file would have been
1019 * ignored for a JRE started by another JRE...
1020 * .. skipped for JRE 1.5 and beyond.
1021 * .. not even checked for pre 1.5.
1022 */
1023 if ((env_in = getenv(ENV_ENTRY)) != NULL) {
1024 if (*env_in != '\0')
1025 *main_class = JLI_StringDup(env_in);
1026 return;
1027 }
1028
1029 /*
1030 * Scan through the arguments for options relevant to multiple JRE
1031 * support. Multiple JRE support existed in JRE versions 1.5 thru 1.8.
1032 *
1033 * This capability is no longer available with JRE versions 1.9 and later.
1034 * These command line options are reported as errors.
1035 */
1036 argc--;
1037 argv++;
1038 while ((arg = *argv) != 0 && *arg == '-') {
1039 if (JLI_StrCCmp(arg, "-version:") == 0) {
1040 JLI_ReportErrorMessage(SPC_ERROR1);
1041 } else if (JLI_StrCmp(arg, "-jre-restrict-search") == 0) {
1042 JLI_ReportErrorMessage(SPC_ERROR2);
1043 } else if (JLI_StrCmp(arg, "-jre-no-restrict-search") == 0) {
1044 JLI_ReportErrorMessage(SPC_ERROR2);
1045 } else {
1046 if (JLI_StrCmp(arg, "-jar") == 0)
1047 jarflag = 1;
1048 if (IsWhiteSpaceOptionArgument(arg) && (argc >= 2)) {
1049 argc--;
1050 argv++;
1051 arg = *argv;
1052 }
1053
1054 /*
1055 * Checking for headless toolkit option in the some way as AWT does:
1056 * "true" means true and any other value means false
1057 */
1058 if (JLI_StrCmp(arg, "-Djava.awt.headless=true") == 0) {
1059 headlessflag = 1;
1060 } else if (JLI_StrCCmp(arg, "-Djava.awt.headless=") == 0) {
1061 headlessflag = 0;
1062 } else if (JLI_StrCCmp(arg, "-splash:") == 0) {
1063 splash_file_name = arg+8;
1064 }
1065 }
1066 argc--;
1067 argv++;
1068 }
1069 if (argc <= 0) { /* No operand? Possibly legit with -[full]version */
1070 operand = NULL;
1071 } else {
1072 argc--;
1123 JLI_StrCat(splash_jar_entry, splash_jar_name);
1124 putenv(splash_jar_entry);
1125 }
1126
1127
1128 /*
1129 * "Valid" returns (other than unrecoverable errors) follow. Set
1130 * main_class as a side-effect of this routine.
1131 */
1132 if (info.main_class != NULL)
1133 *main_class = JLI_StringDup(info.main_class);
1134
1135 if (info.jre_version == NULL) {
1136 JLI_FreeManifest();
1137 return;
1138 }
1139
1140 }
1141
1142 /*
1143 * Parses command line arguments. Returns JNI_FALSE if launcher
1144 * should exit without starting vm, returns JNI_TRUE if vm needs
1145 * to be started to process given options. *pret (the launcher
1146 * process return value) is set to 0 for a normal exit.
1147 */
1148 static jboolean
1149 ParseArguments(int *pargc, char ***pargv,
1150 int *pmode, char **pwhat,
1151 int *pret, const char *jrepath)
1152 {
1153 int argc = *pargc;
1154 char **argv = *pargv;
1155 int mode = LM_UNKNOWN;
1156 char *arg;
1157
1158 *pret = 0;
1159
1160 while ((arg = *argv) != 0 && *arg == '-') {
1161 argv++; --argc;
1162 if (JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) {
1163 ARG_CHECK (argc, ARG_ERROR1, arg);
1164 SetClassPath(*argv);
1165 mode = LM_CLASS;
1166 argv++; --argc;
1167 } else if (JLI_StrCmp(arg, "-modulepath") == 0 || JLI_StrCmp(arg, "-mp") == 0) {
1168 ARG_CHECK (argc, ARG_ERROR4, arg);
1169 SetModulePath(*argv);
1170 argv++; --argc;
1171 } else if (JLI_StrCmp(arg, "-upgrademodulepath") == 0) {
1172 ARG_CHECK (argc, ARG_ERROR4, arg);
1173 SetUpgradeModulePath(*argv);
1174 argv++; --argc;
1175 } else if (JLI_StrCmp(arg, "-jar") == 0) {
1176 ARG_CHECK (argc, ARG_ERROR2, arg);
1177 mode = LM_JAR;
1178 } else if (JLI_StrCmp(arg, "-m") == 0) {
1179 ARG_CHECK (argc, ARG_ERROR5, arg);
1180 SetMainModule(*argv);
1181 mode = LM_MODULE;
1182 } else if (JLI_StrCmp(arg, "-addmods") == 0) {
1183 ARG_CHECK (argc, ARG_ERROR6, arg);
1184 SetAddModulesProp(*argv);
1185 argv++; --argc;
1186 } else if (JLI_StrCmp(arg, "-limitmods") == 0) {
1187 ARG_CHECK (argc, ARG_ERROR6, arg);
1188 SetLimitModulesProp(*argv);
1189 argv++; --argc;
1190 } else if (JLI_StrCmp(arg, "-listmods") == 0 ||
1191 JLI_StrCCmp(arg, "-listmods:") == 0) {
1192 listModules = arg;
1193 return JNI_TRUE;
1194 } else if (JLI_StrCCmp(arg, "-XaddReads:") == 0) {
1195 static jint n;
1196 char *value = arg + 11;
1197 SetAddReadsProp(n++, value);
1198 } else if (JLI_StrCCmp(arg, "-XaddExports:") == 0) {
1199 static jint n;
1200 char *value = arg + 13;
1201 SetAddExportsProp(n++, value);
1202 } else if (JLI_StrCCmp(arg, "-Xpatch:") == 0) {
1203 static jint n;
1204 char *value = arg + 8;
1205 SetPatchProp(n++, value);
1206 } else if (JLI_StrCmp(arg, "-help") == 0 ||
1207 JLI_StrCmp(arg, "-h") == 0 ||
1208 JLI_StrCmp(arg, "-?") == 0) {
1209 printUsage = JNI_TRUE;
1210 return JNI_TRUE;
1211 } else if (JLI_StrCmp(arg, "-version") == 0) {
1212 printVersion = JNI_TRUE;
1213 return JNI_TRUE;
1214 } else if (JLI_StrCmp(arg, "-showversion") == 0) {
1215 showVersion = JNI_TRUE;
1216 } else if (JLI_StrCmp(arg, "--dry-run") == 0) {
1217 dryRun = JNI_TRUE;
1218 } else if (JLI_StrCmp(arg, "-X") == 0) {
1219 printXUsage = JNI_TRUE;
1220 return JNI_TRUE;
1221 /*
1222 * The following case checks for -XshowSettings OR -XshowSetting:SUBOPT.
1223 * In the latter case, any SUBOPT value not recognized will default to "all"
1224 */
1225 } else if (JLI_StrCmp(arg, "-XshowSettings") == 0 ||
1226 JLI_StrCCmp(arg, "-XshowSettings:") == 0) {
1265 } else if (JLI_StrCmp(arg, "-checksource") == 0 ||
1266 JLI_StrCmp(arg, "-cs") == 0 ||
1267 JLI_StrCmp(arg, "-noasyncgc") == 0) {
1268 /* No longer supported */
1269 JLI_ReportErrorMessage(ARG_WARN, arg);
1270 } else if (JLI_StrCCmp(arg, "-splash:") == 0) {
1271 ; /* Ignore machine independent options already handled */
1272 } else if (ProcessPlatformOption(arg)) {
1273 ; /* Processing of platform dependent options */
1274 } else if (RemovableOption(arg)) {
1275 ; /* Do not pass option to vm. */
1276 } else {
1277 /* java.class.path set on the command line */
1278 if (JLI_StrCCmp(arg, "-Djava.class.path=") == 0) {
1279 _have_classpath = JNI_TRUE;
1280 }
1281 AddOption(arg, NULL);
1282 }
1283 }
1284
1285 if (--argc >= 0) {
1286 *pwhat = *argv++;
1287 }
1288
1289 if (*pwhat == NULL) {
1290 *pret = 1;
1291 } else if (mode == LM_UNKNOWN) {
1292 /* default to LM_CLASS if -m, -jar and -cp options are
1293 * not specified */
1294 if (!_have_classpath) {
1295 SetClassPath(".");
1296 }
1297 mode = LM_CLASS;
1298 }
1299
1300 if (argc >= 0) {
1301 *pargc = argc;
1302 *pargv = argv;
1303 }
1304
1305 *pmode = mode;
1675 NULL_CHECK(cls);
1676 NULL_CHECK(showSettingsID = (*env)->GetStaticMethodID(env, cls,
1677 "showSettings", "(ZLjava/lang/String;JJJZ)V"));
1678 NULL_CHECK(joptString = (*env)->NewStringUTF(env, optString));
1679 (*env)->CallStaticVoidMethod(env, cls, showSettingsID,
1680 USE_STDERR,
1681 joptString,
1682 (jlong)initialHeapSize,
1683 (jlong)maxHeapSize,
1684 (jlong)threadStackSize,
1685 ServerClassMachine());
1686 }
1687
1688 /**
1689 * List modules supported by the runtime
1690 */
1691 static void
1692 ListModules(JNIEnv *env, char *optString)
1693 {
1694 jmethodID listModulesID;
1695 jstring joptString;
1696 jclass cls = GetLauncherHelperClass(env);
1697 NULL_CHECK(cls);
1698 NULL_CHECK(listModulesID = (*env)->GetStaticMethodID(env, cls,
1699 "listModules", "(ZLjava/lang/String;)V"));
1700 NULL_CHECK(joptString = (*env)->NewStringUTF(env, optString));
1701 (*env)->CallStaticVoidMethod(env, cls, listModulesID,
1702 USE_STDERR,
1703 joptString);
1704 }
1705
1706 /*
1707 * Prints default usage or the Xusage message, see sun.launcher.LauncherHelper.java
1708 */
1709 static void
1710 PrintUsage(JNIEnv* env, jboolean doXUsage)
1711 {
1712 jmethodID initHelp, vmSelect, vmSynonym, vmErgo, printHelp, printXUsageMessage;
1713 jstring jprogname, vm1, vm2;
1714 int i;
1715 jclass cls = GetLauncherHelperClass(env);
|
82
83 /*
84 * Entries for splash screen environment variables.
85 * putenv is performed in SelectVersion. We need
86 * them in memory until UnsetEnv, so they are made static
87 * global instead of auto local.
88 */
89 static char* splash_file_entry = NULL;
90 static char* splash_jar_entry = NULL;
91
92 /*
93 * List of VM options to be specified when the VM is created.
94 */
95 static JavaVMOption *options;
96 static int numOptions, maxOptions;
97
98 /*
99 * Prototypes for functions internal to launcher.
100 */
101 static void SetClassPath(const char *s);
102 static void SetMainModule(const char *s);
103 static void SelectVersion(int argc, char **argv, char **main_class);
104 static void SetJvmEnvironment(int argc, char **argv);
105 static jboolean ParseArguments(int *pargc, char ***pargv,
106 int *pmode, char **pwhat,
107 int *pret, const char *jrepath);
108 static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
109 InvocationFunctions *ifn);
110 static jstring NewPlatformString(JNIEnv *env, char *s);
111 static jclass LoadMainClass(JNIEnv *env, int mode, char *name);
112 static jclass GetApplicationClass(JNIEnv *env);
113
114 static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv);
115 static jboolean AddApplicationOptions(int cpathc, const char **cpathv);
116 static void SetApplicationClassPath(const char**);
117
118 static void PrintJavaVersion(JNIEnv *env, jboolean extraLF);
119 static void PrintUsage(JNIEnv* env, jboolean doXUsage);
120 static void ShowSettings(JNIEnv* env, char *optString);
121 static void ListModules(JNIEnv* env, char *optString);
122
123 static void SetPaths(int argc, char **argv);
124
125 static void DumpState();
126 static jboolean RemovableOption(char *option);
127
128 enum OptionKind {
129 LAUNCHER_OPTION = 0,
130 LAUNCHER_OPTION_WITH_ARGUMENT,
131 LAUNCHER_MAIN_OPTION,
132 VM_LONG_OPTION,
133 VM_LONG_OPTION_WITH_ARGUMENT,
134 VM_OPTION
135 };
136
137 static int GetOpt(int *pargc, char ***pargv, char **poption, char **pvalue);
138 static jboolean IsOptionWithArgument(int argc, char **argv);
139
140 /* Maximum supported entries from jvm.cfg. */
141 #define INIT_MAX_KNOWN_VMS 10
142
143 /* Values for vmdesc.flag */
144 enum vmdesc_flag {
145 VM_UNKNOWN = -1,
146 VM_KNOWN,
147 VM_ALIASED_TO,
148 VM_WARN,
149 VM_ERROR,
150 VM_IF_SERVER_CLASS,
151 VM_IGNORE
152 };
153
154 struct vmdesc {
155 char *name;
156 int flag;
157 char *alias;
158 char *server_class;
159 };
160 static struct vmdesc *knownVMs = NULL;
161 static int knownVMsCount = 0;
162 static int knownVMsLimit = 0;
163
164 static void GrowKnownVMs(int minimum);
165 static int KnownVMIndex(const char* name);
166 static void FreeKnownVMs();
167 static jboolean IsWildCardEnabled();
168
169 /*
170 * This reports error. VM will not be created and no usage is printed.
171 */
172 #define REPORT_ERROR(AC_ok, AC_failure_message, AC_questionable_arg) \
173 do { \
174 if (!AC_ok) { \
175 JLI_ReportErrorMessage(AC_failure_message, AC_questionable_arg); \
176 printUsage = JNI_FALSE; \
177 *pret = 1; \
178 return JNI_FALSE; \
179 } \
180 } while (JNI_FALSE)
181
182 #define ARG_CHECK(AC_arg_count, AC_failure_message, AC_questionable_arg) \
183 do { \
184 if (AC_arg_count < 1) { \
185 JLI_ReportErrorMessage(AC_failure_message, AC_questionable_arg); \
186 printUsage = JNI_TRUE; \
187 *pret = 1; \
188 return JNI_TRUE; \
189 } \
190 } while (JNI_FALSE)
191
192 /*
193 * Running Java code in primordial thread caused many problems. We will
194 * create a new thread to invoke JVM. See 6316197 for more information.
195 */
196 static jlong threadStackSize = 0; /* stack size of the new thread */
197 static jlong maxHeapSize = 0; /* max heap size */
198 static jlong initialHeapSize = 0; /* inital heap size */
199
200 /*
201 * A minimum -Xss stack size suitable for all platforms.
511 * is not required. The main method is invoked here so that extraneous java
512 * stacks are not in the application stack trace.
513 */
514 mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
515 "([Ljava/lang/String;)V");
516 CHECK_EXCEPTION_NULL_LEAVE(mainID);
517
518 /* Invoke main method. */
519 (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
520
521 /*
522 * The launcher's exit code (in the absence of calls to
523 * System.exit) will be non-zero if main threw an exception.
524 */
525 ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
526
527 LEAVE();
528 }
529
530 /*
531 * Test if the given name is one of the class path options.
532 */
533 static jboolean
534 IsClassPathOption(const char* name) {
535 return JLI_StrCmp(name, "-classpath") == 0 ||
536 JLI_StrCmp(name, "-cp") == 0 ||
537 JLI_StrCmp(name, "--class-path") == 0;
538 }
539
540 /*
541 * Test if the given name is a launcher option taking the main entry point.
542 */
543 static jboolean
544 IsLauncherMainOption(const char* name) {
545 return JLI_StrCmp(name, "--module") == 0 ||
546 JLI_StrCmp(name, "-m") == 0;
547 }
548
549 /*
550 * Test if the given name is a white-space launcher option.
551 */
552 static jboolean
553 IsLauncherOption(const char* name) {
554 return IsClassPathOption(name) ||
555 IsLauncherMainOption(name) ||
556 JLI_StrCmp(name, "--list-modules") == 0;
557 }
558
559 #ifndef OLD_MODULE_OPTIONS
560 /*
561 * Old module options for transition
562 */
563 static jboolean
564 IsOldModuleOption(const char* name) {
565 return JLI_StrCmp(name, "-modulepath") == 0 ||
566 JLI_StrCmp(name, "-mp") == 0 ||
567 JLI_StrCmp(name, "-upgrademodulepath") == 0 ||
568 JLI_StrCmp(name, "-addmods") == 0 ||
569 JLI_StrCmp(name, "-limitmods") == 0;
570 }
571 #endif
572
573 /*
574 * Test if the given name is a module-system white-space option that
575 * will be passed to the VM with its corresponding long-form option
576 * name and "=" delimiter.
577 */
578 static jboolean
579 IsModuleOption(const char* name) {
580 return JLI_StrCmp(name, "--module-path") == 0 ||
581 JLI_StrCmp(name, "-p") == 0 ||
582 JLI_StrCmp(name, "--upgrade-module-path") == 0 ||
583 JLI_StrCmp(name, "--add-modules") == 0 ||
584 JLI_StrCmp(name, "--limit-modules") == 0 ||
585 JLI_StrCmp(name, "--add-exports") == 0 ||
586 JLI_StrCmp(name, "--add-reads") == 0 ||
587 JLI_StrCmp(name, "--patch-module") == 0 ||
588 IsOldModuleOption(name);
589 }
590
591 /*
592 * Test if the given name has a white space option.
593 */
594 jboolean
595 IsWhiteSpaceOption(const char* name) {
596 return IsModuleOption(name) ||
597 IsLauncherOption(name);
598 }
599
600 /*
601 * Checks the command line options to find which JVM type was
602 * specified. If no command line option was given for the JVM type,
603 * the default type is used. The environment variable
604 * JDK_ALTERNATE_VM and the command line option -XXaltjvm= are also
605 * checked as ways of specifying which JVM type to invoke.
606 */
607 char *
608 CheckJvmType(int *pargc, char ***argv, jboolean speculative) {
609 int i, argi;
610 int argc;
611 char **newArgv;
612 int newArgvIdx = 0;
613 int isVMType;
614 int jvmidx = -1;
615 char *jvmtype = getenv("JDK_ALTERNATE_VM");
616
617 argc = *pargc;
618
619 /* To make things simpler we always copy the argv array */
620 newArgv = JLI_MemAlloc((argc + 1) * sizeof(char *));
621
622 /* The program name is always present */
623 newArgv[newArgvIdx++] = (*argv)[0];
624
625 for (argi = 1; argi < argc; argi++) {
626 char *arg = (*argv)[argi];
627 isVMType = 0;
628
629 if (IsJavaArgs()) {
630 if (arg[0] != '-') {
631 newArgv[newArgvIdx++] = arg;
632 continue;
633 }
634 } else {
635 if (IsWhiteSpaceOption(arg)) {
636 newArgv[newArgvIdx++] = arg;
637 argi++;
638 if (argi < argc) {
639 newArgv[newArgvIdx++] = (*argv)[argi];
640 }
641 continue;
642 }
643 if (arg[0] != '-') break;
644 }
645
646 /* Did the user pass an explicit VM type? */
647 i = KnownVMIndex(arg);
648 if (i >= 0) {
649 jvmtype = knownVMs[jvmidx = i].name + 1; /* skip the - */
650 isVMType = 1;
651 *pargc = *pargc - 1;
652 }
653
654 /* Did the user specify an "alternate" VM? */
655 else if (JLI_StrCCmp(arg, "-XXaltjvm=") == 0 || JLI_StrCCmp(arg, "-J-XXaltjvm=") == 0) {
757 * leaving the arg list intact. The first use is for the JVM flag
758 * -XX:NativeMemoryTracking=value.
759 */
760 static void
761 SetJvmEnvironment(int argc, char **argv) {
762
763 static const char* NMT_Env_Name = "NMT_LEVEL_";
764 int i;
765 for (i = 0; i < argc; i++) {
766 char *arg = argv[i];
767 /*
768 * Since this must be a VM flag we stop processing once we see
769 * an argument the launcher would not have processed beyond (such
770 * as -version or -h), or an argument that indicates the following
771 * arguments are for the application (i.e. the main class name, or
772 * the -jar argument).
773 */
774 if (i > 0) {
775 char *prev = argv[i - 1];
776 // skip non-dash arg preceded by class path specifiers
777 if (*arg != '-' && IsWhiteSpaceOption(prev)) {
778 continue;
779 }
780
781 if (*arg != '-'
782 || JLI_StrCmp(arg, "-version") == 0
783 || JLI_StrCmp(arg, "-fullversion") == 0
784 || JLI_StrCmp(arg, "-help") == 0
785 || JLI_StrCmp(arg, "--help") == 0
786 || JLI_StrCmp(arg, "-?") == 0
787 || JLI_StrCmp(arg, "-jar") == 0
788 || JLI_StrCmp(arg, "-X") == 0) {
789 return;
790 }
791 }
792 /*
793 * The following case checks for "-XX:NativeMemoryTracking=value".
794 * If value is non null, an environmental variable set to this value
795 * will be created to be used by the JVM.
796 * The argument is passed to the JVM, which will check validity.
797 * The JVM is responsible for removing the env variable.
798 */
799 if (JLI_StrCCmp(arg, "-XX:NativeMemoryTracking=") == 0) {
800 int retval;
801 // get what follows this parameter, include "="
802 size_t pnlen = JLI_StrLen("-XX:NativeMemoryTracking=");
803 if (JLI_StrLen(arg) > pnlen) {
804 char* value = arg + pnlen;
805 size_t pbuflen = pnlen + JLI_StrLen(value) + 10; // 10 max pid digits
939 * we might just get one, in which case we simply ignore it, and let the
940 * caller deal with it
941 */
942 if (s == NULL)
943 return;
944 s = JLI_WildcardExpandClasspath(s);
945 if (sizeof(format) - 2 + JLI_StrLen(s) < JLI_StrLen(s))
946 // s is became corrupted after expanding wildcards
947 return;
948 def = JLI_MemAlloc(sizeof(format)
949 - 2 /* strlen("%s") */
950 + JLI_StrLen(s));
951 sprintf(def, format, s);
952 AddOption(def, NULL);
953 if (s != orig)
954 JLI_MemFree((char *) s);
955 _have_classpath = JNI_TRUE;
956 }
957
958 static void
959 AddLongFormOption(const char *option, const char *arg)
960 {
961 static const char format[] = "%s=%s";
962 char *def;
963 size_t def_len;
964
965 def_len = JLI_StrLen(option)+1+JLI_StrLen(arg)+1;
966 def = JLI_MemAlloc(def_len);
967 JLI_Snprintf(def, def_len, format, option, arg);
968 AddOption(def, NULL);
969 }
970
971 static void
972 SetMainModule(const char *s)
973 {
974 static const char format[] = "-Djdk.module.main=%s";
975 char* slash = JLI_StrChr(s, '/');
976 size_t s_len, def_len;
977 char *def;
978
979 /* value may be <module> or <module>/<mainclass> */
980 if (slash == NULL) {
981 s_len = JLI_StrLen(s);
982 } else {
983 s_len = (size_t) (slash - s);
984 }
985 def_len = sizeof(format)
986 - 2 /* strlen("%s") */
987 + s_len;
988 def = JLI_MemAlloc(def_len);
989 JLI_Snprintf(def, def_len, format, s);
990 AddOption(def, NULL);
991 }
992
993 /*
994 * The SelectVersion() routine ensures that an appropriate version of
995 * the JRE is running. The specification for the appropriate version
996 * is obtained from either the manifest of a jar file (preferred) or
997 * from command line options.
998 * The routine also parses splash screen command line options and
999 * passes on their values in private environment variables.
1000 */
1001 static void
1002 SelectVersion(int argc, char **argv, char **main_class)
1003 {
1004 char *arg;
1005 char *operand;
1006 char *version = NULL;
1007 char *jre = NULL;
1008 int jarflag = 0;
1009 int headlessflag = 0;
1010 int restrict_search = -1; /* -1 implies not known */
1011 manifest_info info;
1012 char env_entry[MAXNAMELEN + 24] = ENV_ENTRY "=";
1013 char *splash_file_name = NULL;
1014 char *splash_jar_name = NULL;
1015 char *env_in;
1016 int res;
1017 jboolean has_arg;
1018
1019 /*
1020 * If the version has already been selected, set *main_class
1021 * with the value passed through the environment (if any) and
1022 * simply return.
1023 */
1024
1025 /*
1026 * This environmental variable can be set by mJRE capable JREs
1027 * [ 1.5 thru 1.8 ]. All other aspects of mJRE processing have been
1028 * stripped by those JREs. This environmental variable allows 1.9+
1029 * JREs to be started by these mJRE capable JREs.
1030 * Note that mJRE directives in the jar manifest file would have been
1031 * ignored for a JRE started by another JRE...
1032 * .. skipped for JRE 1.5 and beyond.
1033 * .. not even checked for pre 1.5.
1034 */
1035 if ((env_in = getenv(ENV_ENTRY)) != NULL) {
1036 if (*env_in != '\0')
1037 *main_class = JLI_StringDup(env_in);
1038 return;
1039 }
1040
1041 /*
1042 * Scan through the arguments for options relevant to multiple JRE
1043 * support. Multiple JRE support existed in JRE versions 1.5 thru 1.8.
1044 *
1045 * This capability is no longer available with JRE versions 1.9 and later.
1046 * These command line options are reported as errors.
1047 */
1048
1049 argc--;
1050 argv++;
1051 while ((arg = *argv) != 0 && *arg == '-') {
1052 has_arg = IsOptionWithArgument(argc, argv);
1053 if (JLI_StrCCmp(arg, "-version:") == 0) {
1054 JLI_ReportErrorMessage(SPC_ERROR1);
1055 } else if (JLI_StrCmp(arg, "-jre-restrict-search") == 0) {
1056 JLI_ReportErrorMessage(SPC_ERROR2);
1057 } else if (JLI_StrCmp(arg, "-jre-no-restrict-search") == 0) {
1058 JLI_ReportErrorMessage(SPC_ERROR2);
1059 } else {
1060 if (JLI_StrCmp(arg, "-jar") == 0)
1061 jarflag = 1;
1062 if (IsWhiteSpaceOption(arg)) {
1063 if (has_arg) {
1064 argc--;
1065 argv++;
1066 arg = *argv;
1067 }
1068 }
1069
1070 /*
1071 * Checking for headless toolkit option in the some way as AWT does:
1072 * "true" means true and any other value means false
1073 */
1074 if (JLI_StrCmp(arg, "-Djava.awt.headless=true") == 0) {
1075 headlessflag = 1;
1076 } else if (JLI_StrCCmp(arg, "-Djava.awt.headless=") == 0) {
1077 headlessflag = 0;
1078 } else if (JLI_StrCCmp(arg, "-splash:") == 0) {
1079 splash_file_name = arg+8;
1080 }
1081 }
1082 argc--;
1083 argv++;
1084 }
1085 if (argc <= 0) { /* No operand? Possibly legit with -[full]version */
1086 operand = NULL;
1087 } else {
1088 argc--;
1139 JLI_StrCat(splash_jar_entry, splash_jar_name);
1140 putenv(splash_jar_entry);
1141 }
1142
1143
1144 /*
1145 * "Valid" returns (other than unrecoverable errors) follow. Set
1146 * main_class as a side-effect of this routine.
1147 */
1148 if (info.main_class != NULL)
1149 *main_class = JLI_StringDup(info.main_class);
1150
1151 if (info.jre_version == NULL) {
1152 JLI_FreeManifest();
1153 return;
1154 }
1155
1156 }
1157
1158 /*
1159 * Test if the current argv is an option, i.e. with a leading `-`
1160 * and followed with an argument without a leading `-`.
1161 */
1162 static jboolean
1163 IsOptionWithArgument(int argc, char** argv) {
1164 char* option;
1165 char* arg;
1166
1167 if (argc <= 1)
1168 return JNI_FALSE;
1169
1170 option = *argv;
1171 arg = *(argv+1);
1172 return *option == '-' && *arg != '-';
1173 }
1174
1175 /*
1176 * Gets the option, and its argument if the option has an argument.
1177 * It will update *pargc, **pargv to the next option.
1178 */
1179 static int
1180 GetOpt(int *pargc, char ***pargv, char **poption, char **pvalue) {
1181 int argc = *pargc;
1182 char** argv = *pargv;
1183 char* arg = *argv;
1184
1185 char* option = arg;
1186 char* value = NULL;
1187 char* equals = NULL;
1188 int kind = LAUNCHER_OPTION;
1189 jboolean has_arg = JNI_FALSE;
1190
1191 // check if this option may be a white-space option with an argument
1192 has_arg = IsOptionWithArgument(argc, argv);
1193
1194 argv++; --argc;
1195 if (IsLauncherOption(arg)) {
1196 if (has_arg) {
1197 value = *argv;
1198 argv++; --argc;
1199 }
1200 if (IsLauncherMainOption(arg)) {
1201 kind = LAUNCHER_MAIN_OPTION;
1202 } else {
1203 kind = LAUNCHER_OPTION_WITH_ARGUMENT;
1204 }
1205 } else if (IsModuleOption(arg)) {
1206 kind = VM_LONG_OPTION_WITH_ARGUMENT;
1207 if (has_arg) {
1208 value = *argv;
1209 argv++; --argc;
1210 }
1211
1212 /*
1213 * Support short form alias
1214 */
1215 if (JLI_StrCmp(arg, "-p") == 0) {
1216 option = "--module-path";
1217 }
1218
1219 } else if (JLI_StrCCmp(arg, "--") == 0 && (equals = JLI_StrChr(arg, '=')) != NULL) {
1220 value = equals+1;
1221 if (JLI_StrCCmp(arg, "--list-modules=") == 0 ||
1222 JLI_StrCCmp(arg, "--module=") == 0 ||
1223 JLI_StrCCmp(arg, "--class-path=") == 0) {
1224 kind = LAUNCHER_OPTION_WITH_ARGUMENT;
1225 } else {
1226 kind = VM_LONG_OPTION;
1227 }
1228 }
1229
1230 #ifndef OLD_MODULE_OPTIONS
1231 // for transition to support both old and new syntax
1232 if (JLI_StrCmp(arg, "-modulepath") == 0 ||
1233 JLI_StrCmp(arg, "-mp") == 0) {
1234 option = "--module-path";
1235 } else if (JLI_StrCmp(arg, "-upgrademodulepath") == 0) {
1236 option = "--upgrade-module-path";
1237 } else if (JLI_StrCmp(arg, "-addmods") == 0) {
1238 option = "--add-modules";
1239 } else if (JLI_StrCmp(arg, "-limitmods") == 0) {
1240 option = "--limit-modules";
1241 } else if (JLI_StrCCmp(arg, "-XaddExports:") == 0) {
1242 option = "--add-exports";
1243 value = arg + 13;
1244 kind = VM_LONG_OPTION_WITH_ARGUMENT;
1245 } else if (JLI_StrCCmp(arg, "-XaddReads:") == 0) {
1246 option = "--add-reads";
1247 value = arg + 11;
1248 kind = VM_LONG_OPTION_WITH_ARGUMENT;
1249 } else if (JLI_StrCCmp(arg, "-Xpatch:") == 0) {
1250 option = "--patch-module";
1251 value = arg + 8;
1252 kind = VM_LONG_OPTION_WITH_ARGUMENT;
1253 }
1254 #endif
1255
1256 *pargc = argc;
1257 *pargv = argv;
1258 *poption = option;
1259 *pvalue = value;
1260 return kind;
1261 }
1262
1263 /*
1264 * Parses command line arguments. Returns JNI_FALSE if launcher
1265 * should exit without starting vm, returns JNI_TRUE if vm needs
1266 * to be started to process given options. *pret (the launcher
1267 * process return value) is set to 0 for a normal exit.
1268 */
1269 static jboolean
1270 ParseArguments(int *pargc, char ***pargv,
1271 int *pmode, char **pwhat,
1272 int *pret, const char *jrepath)
1273 {
1274 int argc = *pargc;
1275 char **argv = *pargv;
1276 int mode = LM_UNKNOWN;
1277 char *arg;
1278
1279 *pret = 0;
1280
1281 while ((arg = *argv) != 0 && *arg == '-') {
1282 char *option = NULL;
1283 char *value = NULL;
1284 int kind = GetOpt(&argc, &argv, &option, &value);
1285 jboolean has_arg = value != NULL;
1286
1287 /*
1288 * Option to set main entry point
1289 */
1290 if (JLI_StrCmp(arg, "-jar") == 0) {
1291 ARG_CHECK(argc, ARG_ERROR2, arg);
1292 mode = LM_JAR;
1293 } else if (JLI_StrCmp(arg, "--module") == 0 ||
1294 JLI_StrCCmp(arg, "--module=") == 0 ||
1295 JLI_StrCmp(arg, "-m") == 0) {
1296 REPORT_ERROR (has_arg, ARG_ERROR5, arg);
1297 SetMainModule(value);
1298 mode = LM_MODULE;
1299 if (has_arg) {
1300 *pwhat = value;
1301 break;
1302 }
1303 } else if (JLI_StrCmp(arg, "--class-path") == 0 ||
1304 JLI_StrCCmp(arg, "--class-path=") == 0 ||
1305 JLI_StrCmp(arg, "-classpath") == 0 ||
1306 JLI_StrCmp(arg, "-cp") == 0) {
1307 REPORT_ERROR (has_arg, ARG_ERROR1, arg);
1308 SetClassPath(value);
1309 mode = LM_CLASS;
1310 } else if (JLI_StrCmp(arg, "--list-modules") == 0 ||
1311 JLI_StrCCmp(arg, "--list-modules=") == 0) {
1312 listModules = arg;
1313
1314 // set listModules to --list-modules=<module-names> if argument is specified
1315 if (JLI_StrCmp(arg, "--list-modules") == 0 && has_arg) {
1316 static const char format[] = "%s=%s";
1317 size_t buflen = JLI_StrLen(option)+2+JLI_StrLen(value);
1318 listModules = JLI_MemAlloc(buflen);
1319 JLI_Snprintf(listModules, buflen, format, option, value);
1320 }
1321 return JNI_TRUE;
1322 /*
1323 * Parse white-space options
1324 */
1325 } else if (has_arg) {
1326 if (kind == VM_LONG_OPTION) {
1327 AddOption(option, NULL);
1328 } else if (kind == VM_LONG_OPTION_WITH_ARGUMENT) {
1329 AddLongFormOption(option, value);
1330 }
1331 /*
1332 * Error missing argument
1333 */
1334 } else if (!has_arg && IsWhiteSpaceOption(arg)) {
1335 if (JLI_StrCmp(arg, "--module-path") == 0 ||
1336 JLI_StrCmp(arg, "-p") == 0 ||
1337 JLI_StrCmp(arg, "--upgrade-module-path") == 0) {
1338 REPORT_ERROR (has_arg, ARG_ERROR4, arg);
1339 } else if (JLI_StrCmp(arg, "--add-modules") == 0 ||
1340 JLI_StrCmp(arg, "--limit-modules") == 0 ||
1341 JLI_StrCmp(arg, "--add-exports") == 0 ||
1342 JLI_StrCmp(arg, "--add-reads") == 0 ||
1343 JLI_StrCmp(arg, "--patch-module") == 0) {
1344 REPORT_ERROR (has_arg, ARG_ERROR6, arg);
1345 }
1346 #ifndef OLD_MODULE_OPTIONS
1347 else if (JLI_StrCmp(arg, "-modulepath") == 0 ||
1348 JLI_StrCmp(arg, "-mp") == 0 ||
1349 JLI_StrCmp(arg, "-upgrademodulepath") == 0) {
1350 REPORT_ERROR (has_arg, ARG_ERROR4, arg);
1351 } else if (JLI_StrCmp(arg, "-addmods") == 0 ||
1352 JLI_StrCmp(arg, "-limitmods") == 0) {
1353 REPORT_ERROR (has_arg, ARG_ERROR6, arg);
1354 }
1355 #endif
1356 /*
1357 * The following cases will cause the argument parsing to stop
1358 */
1359 } else if (JLI_StrCmp(arg, "--help") == 0 ||
1360 JLI_StrCmp(arg, "-help") == 0 ||
1361 JLI_StrCmp(arg, "-h") == 0 ||
1362 JLI_StrCmp(arg, "-?") == 0) {
1363 printUsage = JNI_TRUE;
1364 return JNI_TRUE;
1365 } else if (JLI_StrCmp(arg, "-version") == 0) {
1366 printVersion = JNI_TRUE;
1367 return JNI_TRUE;
1368 } else if (JLI_StrCmp(arg, "-showversion") == 0) {
1369 showVersion = JNI_TRUE;
1370 } else if (JLI_StrCmp(arg, "--dry-run") == 0) {
1371 dryRun = JNI_TRUE;
1372 } else if (JLI_StrCmp(arg, "-X") == 0) {
1373 printXUsage = JNI_TRUE;
1374 return JNI_TRUE;
1375 /*
1376 * The following case checks for -XshowSettings OR -XshowSetting:SUBOPT.
1377 * In the latter case, any SUBOPT value not recognized will default to "all"
1378 */
1379 } else if (JLI_StrCmp(arg, "-XshowSettings") == 0 ||
1380 JLI_StrCCmp(arg, "-XshowSettings:") == 0) {
1419 } else if (JLI_StrCmp(arg, "-checksource") == 0 ||
1420 JLI_StrCmp(arg, "-cs") == 0 ||
1421 JLI_StrCmp(arg, "-noasyncgc") == 0) {
1422 /* No longer supported */
1423 JLI_ReportErrorMessage(ARG_WARN, arg);
1424 } else if (JLI_StrCCmp(arg, "-splash:") == 0) {
1425 ; /* Ignore machine independent options already handled */
1426 } else if (ProcessPlatformOption(arg)) {
1427 ; /* Processing of platform dependent options */
1428 } else if (RemovableOption(arg)) {
1429 ; /* Do not pass option to vm. */
1430 } else {
1431 /* java.class.path set on the command line */
1432 if (JLI_StrCCmp(arg, "-Djava.class.path=") == 0) {
1433 _have_classpath = JNI_TRUE;
1434 }
1435 AddOption(arg, NULL);
1436 }
1437 }
1438
1439 if (*pwhat == NULL && --argc >= 0) {
1440 *pwhat = *argv++;
1441 }
1442
1443 if (*pwhat == NULL) {
1444 *pret = 1;
1445 } else if (mode == LM_UNKNOWN) {
1446 /* default to LM_CLASS if -m, -jar and -cp options are
1447 * not specified */
1448 if (!_have_classpath) {
1449 SetClassPath(".");
1450 }
1451 mode = LM_CLASS;
1452 }
1453
1454 if (argc >= 0) {
1455 *pargc = argc;
1456 *pargv = argv;
1457 }
1458
1459 *pmode = mode;
1829 NULL_CHECK(cls);
1830 NULL_CHECK(showSettingsID = (*env)->GetStaticMethodID(env, cls,
1831 "showSettings", "(ZLjava/lang/String;JJJZ)V"));
1832 NULL_CHECK(joptString = (*env)->NewStringUTF(env, optString));
1833 (*env)->CallStaticVoidMethod(env, cls, showSettingsID,
1834 USE_STDERR,
1835 joptString,
1836 (jlong)initialHeapSize,
1837 (jlong)maxHeapSize,
1838 (jlong)threadStackSize,
1839 ServerClassMachine());
1840 }
1841
1842 /**
1843 * List modules supported by the runtime
1844 */
1845 static void
1846 ListModules(JNIEnv *env, char *optString)
1847 {
1848 jmethodID listModulesID;
1849 jstring joptString = NULL;
1850 jclass cls = GetLauncherHelperClass(env);
1851 NULL_CHECK(cls);
1852 NULL_CHECK(listModulesID = (*env)->GetStaticMethodID(env, cls,
1853 "listModules", "(ZLjava/lang/String;)V"));
1854 NULL_CHECK(joptString = (*env)->NewStringUTF(env, optString));
1855 (*env)->CallStaticVoidMethod(env, cls, listModulesID,
1856 USE_STDERR,
1857 joptString);
1858 }
1859
1860 /*
1861 * Prints default usage or the Xusage message, see sun.launcher.LauncherHelper.java
1862 */
1863 static void
1864 PrintUsage(JNIEnv* env, jboolean doXUsage)
1865 {
1866 jmethodID initHelp, vmSelect, vmSynonym, vmErgo, printHelp, printXUsageMessage;
1867 jstring jprogname, vm1, vm2;
1868 int i;
1869 jclass cls = GetLauncherHelperClass(env);
|