92 |
92 |
93 /* |
93 /* |
94 * Prototypes for functions internal to launcher. |
94 * Prototypes for functions internal to launcher. |
95 */ |
95 */ |
96 static void SetClassPath(const char *s); |
96 static void SetClassPath(const char *s); |
97 static void SetModulesBootClassPath(const char *s); |
|
98 static void SelectVersion(int argc, char **argv, char **main_class); |
97 static void SelectVersion(int argc, char **argv, char **main_class); |
99 static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile, |
98 static jboolean ParseArguments(int *pargc, char ***pargv, |
100 char **pclassname, int *pret, const char *jvmpath); |
99 int *pmode, char **pwhat, |
|
100 int *pret, const char *jrepath); |
101 static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv, |
101 static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv, |
102 InvocationFunctions *ifn); |
102 InvocationFunctions *ifn); |
103 static jstring NewPlatformString(JNIEnv *env, char *s); |
103 static jstring NewPlatformString(JNIEnv *env, char *s); |
104 static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc); |
104 static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc); |
105 static jclass LoadMainClass(JNIEnv *env, jboolean isJar, char *name); |
105 static jclass LoadMainClass(JNIEnv *env, int mode, char *name); |
106 |
106 |
107 static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv); |
107 static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv); |
108 static jboolean AddApplicationOptions(int cpathc, const char **cpathv); |
108 static jboolean AddApplicationOptions(int cpathc, const char **cpathv); |
109 static void SetApplicationClassPath(const char**); |
109 static void SetApplicationClassPath(const char**); |
110 |
110 |
156 |
156 |
157 /* |
157 /* |
158 * Running Java code in primordial thread caused many problems. We will |
158 * Running Java code in primordial thread caused many problems. We will |
159 * create a new thread to invoke JVM. See 6316197 for more information. |
159 * create a new thread to invoke JVM. See 6316197 for more information. |
160 */ |
160 */ |
161 static jlong threadStackSize = 0; /* stack size of the new thread */ |
161 static jlong threadStackSize = 0; /* stack size of the new thread */ |
162 static jlong maxHeapSize = 0; /* max heap size */ |
162 static jlong maxHeapSize = 0; /* max heap size */ |
163 static jlong initialHeapSize = 0; /* inital heap size */ |
163 static jlong initialHeapSize = 0; /* inital heap size */ |
164 |
164 |
165 int JNICALL JavaMain(void * args); /* entry point */ |
165 int JNICALL JavaMain(void * args); /* entry point */ |
166 |
166 |
|
167 enum LaunchMode { // cf. sun.launcher.LauncherHelper |
|
168 LM_UNKNOWN = 0, |
|
169 LM_CLASS, |
|
170 LM_JAR |
|
171 }; |
|
172 |
|
173 static const char *launchModeNames[] |
|
174 = { "Unknown", "Main class", "JAR file" }; |
|
175 |
167 typedef struct { |
176 typedef struct { |
168 int argc; |
177 int argc; |
169 char ** argv; |
178 char **argv; |
170 char * jarfile; |
179 int mode; |
171 char * classname; |
180 char *what; |
172 InvocationFunctions ifn; |
181 InvocationFunctions ifn; |
173 } JavaMainArgs; |
182 } JavaMainArgs; |
174 |
183 |
175 /* |
184 /* |
176 * Entry point. |
185 * Entry point. |
177 */ |
186 */ |
187 jboolean cpwildcard, /* classpath wildcard*/ |
196 jboolean cpwildcard, /* classpath wildcard*/ |
188 jboolean javaw, /* windows-only javaw */ |
197 jboolean javaw, /* windows-only javaw */ |
189 jint ergo /* ergonomics class policy */ |
198 jint ergo /* ergonomics class policy */ |
190 ) |
199 ) |
191 { |
200 { |
192 char *jarfile = 0; |
201 int mode = LM_UNKNOWN; |
193 char *classname = 0; |
202 char *what = NULL; |
194 char *cpath = 0; |
203 char *cpath = 0; |
195 char *main_class = NULL; |
204 char *main_class = NULL; |
196 int ret; |
205 int ret; |
197 InvocationFunctions ifn; |
206 InvocationFunctions ifn; |
198 jlong start, end; |
207 jlong start, end; |
275 cpath = "."; |
284 cpath = "."; |
276 } |
285 } |
277 SetClassPath(cpath); |
286 SetClassPath(cpath); |
278 } |
287 } |
279 |
288 |
280 /* |
289 /* Parse command line options; if the return value of |
281 * Parse command line options; if the return value of |
290 * ParseArguments is false, the program should exit. |
282 * ParseArguments is false, the program should exit. |
|
283 */ |
291 */ |
284 if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret, jvmpath)) { |
292 if (!ParseArguments(&argc, &argv, &mode, &what, &ret, jrepath)) |
|
293 { |
285 return(ret); |
294 return(ret); |
286 } |
295 } |
287 |
296 |
288 /* Set bootclasspath for modules */ |
|
289 SetModulesBootClassPath(jrepath); |
|
290 |
|
291 /* Override class path if -jar flag was specified */ |
297 /* Override class path if -jar flag was specified */ |
292 if (jarfile != 0) { |
298 if (mode == LM_JAR) { |
293 SetClassPath(jarfile); |
299 SetClassPath(what); /* Override class path */ |
294 } |
300 } |
295 |
301 |
296 /* set the -Dsun.java.command pseudo property */ |
302 /* set the -Dsun.java.command pseudo property */ |
297 SetJavaCommandLineProp(classname, jarfile, argc, argv); |
303 SetJavaCommandLineProp(what, argc, argv); |
298 |
304 |
299 /* Set the -Dsun.java.launcher pseudo property */ |
305 /* Set the -Dsun.java.launcher pseudo property */ |
300 SetJavaLauncherProp(); |
306 SetJavaLauncherProp(); |
301 |
307 |
302 /* set the -Dsun.java.launcher.* platform properties */ |
308 /* set the -Dsun.java.launcher.* platform properties */ |
303 SetJavaLauncherPlatformProps(); |
309 SetJavaLauncherPlatformProps(); |
304 |
310 |
305 /* Show the splash screen if needed */ |
311 /* Show the splash screen if needed */ |
306 ShowSplashScreen(); |
312 ShowSplashScreen(); |
307 |
313 |
308 return ContinueInNewThread(&ifn, argc, argv, jarfile, classname, ret); |
314 return ContinueInNewThread(&ifn, argc, argv, mode, what, ret); |
309 |
315 |
310 } |
316 } |
311 /* |
317 /* |
312 * Always detach the main thread so that it appears to have ended when |
318 * Always detach the main thread so that it appears to have ended when |
313 * the application's main method exits. This will invoke the |
319 * the application's main method exits. This will invoke the |
351 JavaMain(void * _args) |
357 JavaMain(void * _args) |
352 { |
358 { |
353 JavaMainArgs *args = (JavaMainArgs *)_args; |
359 JavaMainArgs *args = (JavaMainArgs *)_args; |
354 int argc = args->argc; |
360 int argc = args->argc; |
355 char **argv = args->argv; |
361 char **argv = args->argv; |
356 char *jarfile = args->jarfile; |
362 int mode = args->mode; |
357 char *classname = args->classname; |
363 char *what = args->what; |
358 InvocationFunctions ifn = args->ifn; |
364 InvocationFunctions ifn = args->ifn; |
359 |
365 |
360 JavaVM *vm = 0; |
366 JavaVM *vm = 0; |
361 JNIEnv *env = 0; |
367 JNIEnv *env = 0; |
362 jclass mainClass; |
368 jclass mainClass = NULL; |
363 jmethodID mainID; |
369 jmethodID mainID; |
364 jobjectArray mainArgs; |
370 jobjectArray mainArgs; |
365 int ret = 0; |
371 int ret = 0; |
366 jlong start, end; |
372 jlong start, end; |
367 |
373 |
383 if (showSettings != NULL) { |
389 if (showSettings != NULL) { |
384 ShowSettings(env, showSettings); |
390 ShowSettings(env, showSettings); |
385 CHECK_EXCEPTION_LEAVE(1); |
391 CHECK_EXCEPTION_LEAVE(1); |
386 } |
392 } |
387 /* If the user specified neither a class name nor a JAR file */ |
393 /* If the user specified neither a class name nor a JAR file */ |
388 if (printXUsage || printUsage || (jarfile == 0 && classname == 0)) { |
394 if (printXUsage || printUsage || what == 0 || mode == LM_UNKNOWN) { |
389 PrintUsage(env, printXUsage); |
395 PrintUsage(env, printXUsage); |
390 CHECK_EXCEPTION_LEAVE(1); |
396 CHECK_EXCEPTION_LEAVE(1); |
391 LEAVE(); |
397 LEAVE(); |
392 } |
398 } |
393 |
399 |
397 end = CounterGet(); |
403 end = CounterGet(); |
398 JLI_TraceLauncher("%ld micro seconds to InitializeJVM\n", |
404 JLI_TraceLauncher("%ld micro seconds to InitializeJVM\n", |
399 (long)(jint)Counter2Micros(end-start)); |
405 (long)(jint)Counter2Micros(end-start)); |
400 } |
406 } |
401 |
407 |
402 /* At this stage, argc/argv have the applications' arguments */ |
408 /* At this stage, argc/argv have the application's arguments */ |
403 if (JLI_IsTraceLauncher()){ |
409 if (JLI_IsTraceLauncher()){ |
404 int i; |
410 int i; |
405 printf("Main-Class is '%s'\n", classname ? classname : ""); |
411 printf("%s is '%s'\n", launchModeNames[mode], what); |
406 printf("Apps' argc is %d\n", argc); |
412 printf("App's argc is %d\n", argc); |
407 for (i=0; i < argc; i++) { |
413 for (i=0; i < argc; i++) { |
408 printf(" argv[%2d] = '%s'\n", i, argv[i]); |
414 printf(" argv[%2d] = '%s'\n", i, argv[i]); |
409 } |
415 } |
410 } |
416 } |
411 |
417 |
429 * Main-Class attribute gets properly passed through |
435 * Main-Class attribute gets properly passed through |
430 * all environments, |
436 * all environments, |
431 * 2) Remove the vestages of maintaining main_class through |
437 * 2) Remove the vestages of maintaining main_class through |
432 * the environment (and remove these comments). |
438 * the environment (and remove these comments). |
433 */ |
439 */ |
434 if (jarfile != 0) { |
440 mainClass = LoadMainClass(env, mode, what); |
435 mainClass = LoadMainClass(env, JNI_TRUE, jarfile); |
|
436 } else { |
|
437 mainClass = LoadMainClass(env, JNI_FALSE, classname); |
|
438 } |
|
439 CHECK_EXCEPTION_NULL_LEAVE(mainClass); |
441 CHECK_EXCEPTION_NULL_LEAVE(mainClass); |
440 |
442 |
441 /* |
443 /* |
442 * The LoadMainClass not only loads the main class, it will also ensure |
444 * The LoadMainClass not only loads the main class, it will also ensure |
443 * that the main method's signature is correct, therefore further checking |
445 * that the main method's signature is correct, therefore further checking |
707 { |
709 { |
708 char *def; |
710 char *def; |
709 const char *orig = s; |
711 const char *orig = s; |
710 static const char format[] = "-Djava.class.path=%s"; |
712 static const char format[] = "-Djava.class.path=%s"; |
711 s = JLI_WildcardExpandClasspath(s); |
713 s = JLI_WildcardExpandClasspath(s); |
712 def = JLI_MemAlloc(sizeof(format) |
|
713 - 2 /* strlen("%s") */ |
|
714 + JLI_StrLen(s)); |
|
715 sprintf(def, format, s); |
|
716 AddOption(def, NULL); |
|
717 if (s != orig) |
|
718 JLI_MemFree((char *) s); |
|
719 } |
|
720 |
|
721 /* |
|
722 * Set the bootclasspath for modules. |
|
723 * A temporary workaround until jigsaw is integrated into JDK 7. |
|
724 */ |
|
725 static void |
|
726 SetModulesBootClassPath(const char *jrepath) |
|
727 { |
|
728 char *def, *s; |
|
729 char pathname[MAXPATHLEN]; |
|
730 const char separator[] = { FILE_SEPARATOR, '\0' }; |
|
731 const char *orig = jrepath; |
|
732 static const char format[] = "-Xbootclasspath/p:%s"; |
|
733 struct stat statbuf; |
|
734 |
|
735 /* return if jre/lib/rt.jar exists */ |
|
736 JLI_Snprintf(pathname, sizeof(pathname), "%s%slib%srt.jar", jrepath, separator, separator); |
|
737 if (stat(pathname, &statbuf) == 0) { |
|
738 return; |
|
739 } |
|
740 |
|
741 /* return if jre/classes exists */ |
|
742 JLI_Snprintf(pathname, sizeof(pathname), "%s%sclasses", jrepath, separator); |
|
743 if (stat(pathname, &statbuf) == 0) { |
|
744 return; |
|
745 } |
|
746 |
|
747 /* modularized jre */ |
|
748 JLI_Snprintf(pathname, sizeof(pathname), "%s%slib%s*", jrepath, separator, separator); |
|
749 s = (char *) JLI_WildcardExpandClasspath(pathname); |
|
750 def = JLI_MemAlloc(sizeof(format) |
714 def = JLI_MemAlloc(sizeof(format) |
751 - 2 /* strlen("%s") */ |
715 - 2 /* strlen("%s") */ |
752 + JLI_StrLen(s)); |
716 + JLI_StrLen(s)); |
753 sprintf(def, format, s); |
717 sprintf(def, format, s); |
754 AddOption(def, NULL); |
718 AddOption(def, NULL); |
998 } |
962 } |
999 |
963 |
1000 /* |
964 /* |
1001 * Parses command line arguments. Returns JNI_FALSE if launcher |
965 * Parses command line arguments. Returns JNI_FALSE if launcher |
1002 * should exit without starting vm, returns JNI_TRUE if vm needs |
966 * should exit without starting vm, returns JNI_TRUE if vm needs |
1003 * to be started to process given options. *pret (the launcher |
967 * to be started to process given options. *pret (the launcher |
1004 * process return value) is set to 0 for a normal exit. |
968 * process return value) is set to 0 for a normal exit. |
1005 */ |
969 */ |
1006 static jboolean |
970 static jboolean |
1007 ParseArguments(int *pargc, char ***pargv, char **pjarfile, |
971 ParseArguments(int *pargc, char ***pargv, |
1008 char **pclassname, int *pret, const char *jvmpath) |
972 int *pmode, char **pwhat, |
|
973 int *pret, const char *jrepath) |
1009 { |
974 { |
1010 int argc = *pargc; |
975 int argc = *pargc; |
1011 char **argv = *pargv; |
976 char **argv = *pargv; |
1012 jboolean jarflag = JNI_FALSE; |
977 int mode = LM_UNKNOWN; |
1013 char *arg; |
978 char *arg; |
1014 |
979 |
1015 *pret = 0; |
980 *pret = 0; |
1016 |
981 |
1017 while ((arg = *argv) != 0 && *arg == '-') { |
982 while ((arg = *argv) != 0 && *arg == '-') { |
1018 argv++; --argc; |
983 argv++; --argc; |
1019 if (JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) { |
984 if (JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) { |
1020 ARG_CHECK (argc, ARG_ERROR1, arg); |
985 ARG_CHECK (argc, ARG_ERROR1, arg); |
1021 SetClassPath(*argv); |
986 SetClassPath(*argv); |
|
987 mode = LM_CLASS; |
1022 argv++; --argc; |
988 argv++; --argc; |
1023 } else if (JLI_StrCmp(arg, "-jar") == 0) { |
989 } else if (JLI_StrCmp(arg, "-jar") == 0) { |
1024 ARG_CHECK (argc, ARG_ERROR2, arg); |
990 ARG_CHECK (argc, ARG_ERROR2, arg); |
1025 jarflag = JNI_TRUE; |
991 mode = LM_JAR; |
1026 } else if (JLI_StrCmp(arg, "-help") == 0 || |
992 } else if (JLI_StrCmp(arg, "-help") == 0 || |
1027 JLI_StrCmp(arg, "-h") == 0 || |
993 JLI_StrCmp(arg, "-h") == 0 || |
1028 JLI_StrCmp(arg, "-?") == 0) { |
994 JLI_StrCmp(arg, "-?") == 0) { |
1029 printUsage = JNI_TRUE; |
995 printUsage = JNI_TRUE; |
1030 return JNI_TRUE; |
996 return JNI_TRUE; |
1274 if (JLI_IsTraceLauncher()) { |
1245 if (JLI_IsTraceLauncher()) { |
1275 start = CounterGet(); |
1246 start = CounterGet(); |
1276 } |
1247 } |
1277 NULL_CHECK0(cls = FindBootStrapClass(env, "sun/launcher/LauncherHelper")); |
1248 NULL_CHECK0(cls = FindBootStrapClass(env, "sun/launcher/LauncherHelper")); |
1278 NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls, "checkAndLoadMain", |
1249 NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls, "checkAndLoadMain", |
1279 "(ZZLjava/lang/String;)Ljava/lang/Object;")); |
1250 "(ZILjava/lang/String;)Ljava/lang/Class;")); |
1280 str = (*env)->NewStringUTF(env, name); |
1251 str = (*env)->NewStringUTF(env, name); |
1281 result = (*env)->CallStaticObjectMethod(env, cls, mid, JNI_TRUE, isJar, str); |
1252 result = (*env)->CallStaticObjectMethod(env, cls, mid, JNI_TRUE, mode, str); |
1282 |
1253 |
1283 if (JLI_IsTraceLauncher()) { |
1254 if (JLI_IsTraceLauncher()) { |
1284 end = CounterGet(); |
1255 end = CounterGet(); |
1285 printf("%ld micro seconds to load main class\n", |
1256 printf("%ld micro seconds to load main class\n", |
1286 (long)(jint)Counter2Micros(end-start)); |
1257 (long)(jint)Counter2Micros(end-start)); |
1422 * (or jar file name) and the arguments to the class's main method |
1393 * (or jar file name) and the arguments to the class's main method |
1423 * to the instrumentation memory region. The sun.java.command pseudo |
1394 * to the instrumentation memory region. The sun.java.command pseudo |
1424 * property is not exported by HotSpot to the Java layer. |
1395 * property is not exported by HotSpot to the Java layer. |
1425 */ |
1396 */ |
1426 void |
1397 void |
1427 SetJavaCommandLineProp(char *classname, char *jarfile, |
1398 SetJavaCommandLineProp(char *what, int argc, char **argv) |
1428 int argc, char **argv) |
|
1429 { |
1399 { |
1430 |
1400 |
1431 int i = 0; |
1401 int i = 0; |
1432 size_t len = 0; |
1402 size_t len = 0; |
1433 char* javaCommand = NULL; |
1403 char* javaCommand = NULL; |
1434 char* dashDstr = "-Dsun.java.command="; |
1404 char* dashDstr = "-Dsun.java.command="; |
1435 |
1405 |
1436 if (classname == NULL && jarfile == NULL) { |
1406 if (what == NULL) { |
1437 /* unexpected, one of these should be set. just return without |
1407 /* unexpected, one of these should be set. just return without |
1438 * setting the property |
1408 * setting the property |
1439 */ |
1409 */ |
1440 return; |
1410 return; |
1441 } |
1411 } |
1442 |
1412 |
1443 /* if the class name is not set, then use the jarfile name */ |
|
1444 if (classname == NULL) { |
|
1445 classname = jarfile; |
|
1446 } |
|
1447 |
|
1448 /* determine the amount of memory to allocate assuming |
1413 /* determine the amount of memory to allocate assuming |
1449 * the individual components will be space separated |
1414 * the individual components will be space separated |
1450 */ |
1415 */ |
1451 len = JLI_StrLen(classname); |
1416 len = JLI_StrLen(what); |
1452 for (i = 0; i < argc; i++) { |
1417 for (i = 0; i < argc; i++) { |
1453 len += JLI_StrLen(argv[i]) + 1; |
1418 len += JLI_StrLen(argv[i]) + 1; |
1454 } |
1419 } |
1455 |
1420 |
1456 /* allocate the memory */ |
1421 /* allocate the memory */ |
1457 javaCommand = (char*) JLI_MemAlloc(len + JLI_StrLen(dashDstr) + 1); |
1422 javaCommand = (char*) JLI_MemAlloc(len + JLI_StrLen(dashDstr) + 1); |
1458 |
1423 |
1459 /* build the -D string */ |
1424 /* build the -D string */ |
1460 *javaCommand = '\0'; |
1425 *javaCommand = '\0'; |
1461 JLI_StrCat(javaCommand, dashDstr); |
1426 JLI_StrCat(javaCommand, dashDstr); |
1462 JLI_StrCat(javaCommand, classname); |
1427 JLI_StrCat(javaCommand, what); |
1463 |
1428 |
1464 for (i = 0; i < argc; i++) { |
1429 for (i = 0; i < argc; i++) { |
1465 /* the components of the string are space separated. In |
1430 /* the components of the string are space separated. In |
1466 * the case of embedded white space, the relationship of |
1431 * the case of embedded white space, the relationship of |
1467 * the white space separated components to their true |
1432 * the white space separated components to their true |
1477 |
1442 |
1478 /* |
1443 /* |
1479 * JVM would like to know if it's created by a standard Sun launcher, or by |
1444 * JVM would like to know if it's created by a standard Sun launcher, or by |
1480 * user native application, the following property indicates the former. |
1445 * user native application, the following property indicates the former. |
1481 */ |
1446 */ |
1482 void SetJavaLauncherProp() { |
1447 void |
|
1448 SetJavaLauncherProp() { |
1483 AddOption("-Dsun.java.launcher=SUN_STANDARD", NULL); |
1449 AddOption("-Dsun.java.launcher=SUN_STANDARD", NULL); |
1484 } |
1450 } |
1485 |
1451 |
1486 /* |
1452 /* |
1487 * Prints the version information from the java.version and other properties. |
1453 * Prints the version information from the java.version and other properties. |
1911 { |
1877 { |
1912 return _wc_enabled; |
1878 return _wc_enabled; |
1913 } |
1879 } |
1914 |
1880 |
1915 static int |
1881 static int |
1916 ContinueInNewThread(InvocationFunctions* ifn, int argc, |
1882 ContinueInNewThread(InvocationFunctions* ifn, int argc, char **argv, |
1917 char **argv, char *jarfile, char *classname, int ret) |
1883 int mode, char *what, int ret) |
1918 { |
1884 { |
1919 |
1885 |
1920 /* |
1886 /* |
1921 * If user doesn't specify stack size, check if VM has a preference. |
1887 * If user doesn't specify stack size, check if VM has a preference. |
1922 * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will |
1888 * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will |