77 78 /* 79 * Entries for splash screen environment variables. 80 * putenv is performed in SelectVersion. We need 81 * them in memory until UnsetEnv, so they are made static 82 * global instead of auto local. 83 */ 84 static char* splash_file_entry = NULL; 85 static char* splash_jar_entry = NULL; 86 87 /* 88 * List of VM options to be specified when the VM is created. 89 */ 90 static JavaVMOption *options; 91 static int numOptions, maxOptions; 92 93 /* 94 * Prototypes for functions internal to launcher. 95 */ 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); 99 static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile, 100 char **pclassname, int *pret, const char *jvmpath); 101 static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv, 102 InvocationFunctions *ifn); 103 static jstring NewPlatformString(JNIEnv *env, char *s); 104 static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc); 105 static jclass LoadMainClass(JNIEnv *env, jboolean isJar, char *name); 106 107 static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv); 108 static jboolean AddApplicationOptions(int cpathc, const char **cpathv); 109 static void SetApplicationClassPath(const char**); 110 111 static void PrintJavaVersion(JNIEnv *env, jboolean extraLF); 112 static void PrintUsage(JNIEnv* env, jboolean doXUsage); 113 static void ShowSettings(JNIEnv* env, char *optString); 114 115 static void SetPaths(int argc, char **argv); 116 117 static void DumpState(); 118 static jboolean RemovableOption(char *option); 119 120 /* Maximum supported entries from jvm.cfg. */ 121 #define INIT_MAX_KNOWN_VMS 10 122 123 /* Values for vmdesc.flag */ 124 enum vmdesc_flag { 125 VM_UNKNOWN = -1, 147 static void ShowSplashScreen(); 148 static jboolean IsWildCardEnabled(); 149 150 #define ARG_CHECK(n, f, a) if (n < 1) { \ 151 JLI_ReportErrorMessage(f, a); \ 152 printUsage = JNI_TRUE; \ 153 *pret = 1; \ 154 return JNI_TRUE; \ 155 } 156 157 /* 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. 160 */ 161 static jlong threadStackSize = 0; /* stack size of the new thread */ 162 static jlong maxHeapSize = 0; /* max heap size */ 163 static jlong initialHeapSize = 0; /* inital heap size */ 164 165 int JNICALL JavaMain(void * args); /* entry point */ 166 167 typedef struct { 168 int argc; 169 char ** argv; 170 char * jarfile; 171 char * classname; 172 InvocationFunctions ifn; 173 } JavaMainArgs; 174 175 /* 176 * Entry point. 177 */ 178 int 179 JLI_Launch(int argc, char ** argv, /* main argc, argc */ 180 int jargc, const char** jargv, /* java args */ 181 int appclassc, const char** appclassv, /* app classpath */ 182 const char* fullversion, /* full version defined */ 183 const char* dotversion, /* dot version defined */ 184 const char* pname, /* program name */ 185 const char* lname, /* launcher name */ 186 jboolean javaargs, /* JAVA_ARGS */ 187 jboolean cpwildcard, /* classpath wildcard*/ 188 jboolean javaw, /* windows-only javaw */ 189 jint ergo /* ergonomics class policy */ 190 ) 191 { 192 char *jarfile = 0; 193 char *classname = 0; 194 char *cpath = 0; 195 char *main_class = NULL; 196 int ret; 197 InvocationFunctions ifn; 198 jlong start, end; 199 char jvmpath[MAXPATHLEN]; 200 char jrepath[MAXPATHLEN]; 201 202 _fVersion = fullversion; 203 _dVersion = dotversion; 204 _launcher_name = lname; 205 _program_name = pname; 206 _is_java_args = javaargs; 207 _wc_enabled = cpwildcard; 208 _ergo_policy = ergo; 209 210 InitLauncher(javaw); 211 DumpState(); 212 213 /* 260 (long)(jint)Counter2Micros(end-start)); 261 262 ++argv; 263 --argc; 264 265 if (IsJavaArgs()) { 266 /* Preprocess wrapper arguments */ 267 TranslateApplicationArgs(jargc, jargv, &argc, &argv); 268 if (!AddApplicationOptions(appclassc, appclassv)) { 269 return(1); 270 } 271 } else { 272 /* Set default CLASSPATH */ 273 cpath = getenv("CLASSPATH"); 274 if (cpath == NULL) { 275 cpath = "."; 276 } 277 SetClassPath(cpath); 278 } 279 280 /* 281 * Parse command line options; if the return value of 282 * ParseArguments is false, the program should exit. 283 */ 284 if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret, jvmpath)) { 285 return(ret); 286 } 287 288 /* Set bootclasspath for modules */ 289 SetModulesBootClassPath(jrepath); 290 291 /* Override class path if -jar flag was specified */ 292 if (jarfile != 0) { 293 SetClassPath(jarfile); 294 } 295 296 /* set the -Dsun.java.command pseudo property */ 297 SetJavaCommandLineProp(classname, jarfile, argc, argv); 298 299 /* Set the -Dsun.java.launcher pseudo property */ 300 SetJavaLauncherProp(); 301 302 /* set the -Dsun.java.launcher.* platform properties */ 303 SetJavaLauncherPlatformProps(); 304 305 /* Show the splash screen if needed */ 306 ShowSplashScreen(); 307 308 return ContinueInNewThread(&ifn, argc, argv, jarfile, classname, ret); 309 310 } 311 /* 312 * Always detach the main thread so that it appears to have ended when 313 * the application's main method exits. This will invoke the 314 * uncaught exception handler machinery if main threw an 315 * exception. An uncaught exception handler cannot change the 316 * launcher's return code except by calling System.exit. 317 * 318 * Wait for all non-daemon threads to end, then destroy the VM. 319 * This will actually create a trivial new Java waiter thread 320 * named "DestroyJavaVM", but this will be seen as a different 321 * thread from the one that executed main, even though they are 322 * the same C thread. This allows mainThread.join() and 323 * mainThread.isAlive() to work as expected. 324 */ 325 #define LEAVE() \ 326 if ((*vm)->DetachCurrentThread(vm) != 0) { \ 327 JLI_ReportErrorMessage(JVM_ERROR2); \ 328 ret = 1; \ 336 LEAVE(); \ 337 } \ 338 if ((e) == NULL) { \ 339 JLI_ReportErrorMessage(JNI_ERROR); \ 340 LEAVE(); \ 341 } 342 343 #define CHECK_EXCEPTION_LEAVE(rv) \ 344 if ((*env)->ExceptionOccurred(env)) { \ 345 JLI_ReportExceptionDescription(env); \ 346 ret = (rv); \ 347 LEAVE(); \ 348 } 349 350 int JNICALL 351 JavaMain(void * _args) 352 { 353 JavaMainArgs *args = (JavaMainArgs *)_args; 354 int argc = args->argc; 355 char **argv = args->argv; 356 char *jarfile = args->jarfile; 357 char *classname = args->classname; 358 InvocationFunctions ifn = args->ifn; 359 360 JavaVM *vm = 0; 361 JNIEnv *env = 0; 362 jclass mainClass; 363 jmethodID mainID; 364 jobjectArray mainArgs; 365 int ret = 0; 366 jlong start, end; 367 368 /* Initialize the virtual machine */ 369 start = CounterGet(); 370 if (!InitializeJVM(&vm, &env, &ifn)) { 371 JLI_ReportErrorMessage(JVM_ERROR1); 372 exit(1); 373 } 374 375 if (printVersion || showVersion) { 376 PrintJavaVersion(env, showVersion); 377 CHECK_EXCEPTION_LEAVE(0); 378 if (printVersion) { 379 LEAVE(); 380 } 381 } 382 383 if (showSettings != NULL) { 384 ShowSettings(env, showSettings); 385 CHECK_EXCEPTION_LEAVE(1); 386 } 387 /* If the user specified neither a class name nor a JAR file */ 388 if (printXUsage || printUsage || (jarfile == 0 && classname == 0)) { 389 PrintUsage(env, printXUsage); 390 CHECK_EXCEPTION_LEAVE(1); 391 LEAVE(); 392 } 393 394 FreeKnownVMs(); /* after last possible PrintUsage() */ 395 396 if (JLI_IsTraceLauncher()) { 397 end = CounterGet(); 398 JLI_TraceLauncher("%ld micro seconds to InitializeJVM\n", 399 (long)(jint)Counter2Micros(end-start)); 400 } 401 402 /* At this stage, argc/argv have the applications' arguments */ 403 if (JLI_IsTraceLauncher()){ 404 int i; 405 printf("Main-Class is '%s'\n", classname ? classname : ""); 406 printf("Apps' argc is %d\n", argc); 407 for (i=0; i < argc; i++) { 408 printf(" argv[%2d] = '%s'\n", i, argv[i]); 409 } 410 } 411 412 ret = 1; 413 414 /* 415 * Get the application's main class. 416 * 417 * See bugid 5030265. The Main-Class name has already been parsed 418 * from the manifest, but not parsed properly for UTF-8 support. 419 * Hence the code here ignores the value previously extracted and 420 * uses the pre-existing code to reextract the value. This is 421 * possibly an end of release cycle expedient. However, it has 422 * also been discovered that passing some character sets through 423 * the environment has "strange" behavior on some variants of 424 * Windows. Hence, maybe the manifest parsing code local to the 425 * launcher should never be enhanced. 426 * 427 * Hence, future work should either: 428 * 1) Correct the local parsing code and verify that the 429 * Main-Class attribute gets properly passed through 430 * all environments, 431 * 2) Remove the vestages of maintaining main_class through 432 * the environment (and remove these comments). 433 */ 434 if (jarfile != 0) { 435 mainClass = LoadMainClass(env, JNI_TRUE, jarfile); 436 } else { 437 mainClass = LoadMainClass(env, JNI_FALSE, classname); 438 } 439 CHECK_EXCEPTION_NULL_LEAVE(mainClass); 440 441 /* 442 * The LoadMainClass not only loads the main class, it will also ensure 443 * that the main method's signature is correct, therefore further checking 444 * is not required. The main method is invoked here so that extraneous java 445 * stacks are not in the application stack trace. 446 */ 447 mainID = (*env)->GetStaticMethodID(env, mainClass, "main", 448 "([Ljava/lang/String;)V"); 449 CHECK_EXCEPTION_NULL_LEAVE(mainID); 450 451 /* Build argument array */ 452 mainArgs = NewPlatformStringArray(env, argv, argc); 453 CHECK_EXCEPTION_NULL_LEAVE(mainArgs); 454 455 /* Invoke main method. */ 456 (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); 457 458 /* 702 } 703 } 704 705 static void 706 SetClassPath(const char *s) 707 { 708 char *def; 709 const char *orig = s; 710 static const char format[] = "-Djava.class.path=%s"; 711 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) 751 - 2 /* strlen("%s") */ 752 + JLI_StrLen(s)); 753 sprintf(def, format, s); 754 AddOption(def, NULL); 755 if (s != orig) 756 JLI_MemFree((char *) s); 757 } 758 759 /* 760 * The SelectVersion() routine ensures that an appropriate version of 761 * the JRE is running. The specification for the appropriate version 762 * is obtained from either the manifest of a jar file (preferred) or 763 * from command line options. 764 * The routine also parses splash screen command line options and 765 * passes on their values in private environment variables. 766 */ 767 static void 768 SelectVersion(int argc, char **argv, char **main_class) 769 { 770 char *arg; 771 char **new_argv; 772 char **new_argp; 773 char *operand; 774 char *version = NULL; 775 char *jre = NULL; 776 int jarflag = 0; 777 int headlessflag = 0; 778 int restrict_search = -1; /* -1 implies not known */ 779 manifest_info info; 987 (void)JLI_StrCat(env_entry, info.main_class); 988 } else { 989 JLI_ReportErrorMessage(CLS_ERROR5, MAXNAMELEN); 990 exit(1); 991 } 992 } 993 (void)putenv(env_entry); 994 ExecJRE(jre, new_argv); 995 JLI_FreeManifest(); 996 JLI_MemFree(new_argv); 997 return; 998 } 999 1000 /* 1001 * Parses command line arguments. Returns JNI_FALSE if launcher 1002 * should exit without starting vm, returns JNI_TRUE if vm needs 1003 * to be started to process given options. *pret (the launcher 1004 * process return value) is set to 0 for a normal exit. 1005 */ 1006 static jboolean 1007 ParseArguments(int *pargc, char ***pargv, char **pjarfile, 1008 char **pclassname, int *pret, const char *jvmpath) 1009 { 1010 int argc = *pargc; 1011 char **argv = *pargv; 1012 jboolean jarflag = JNI_FALSE; 1013 char *arg; 1014 1015 *pret = 0; 1016 1017 while ((arg = *argv) != 0 && *arg == '-') { 1018 argv++; --argc; 1019 if (JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) { 1020 ARG_CHECK (argc, ARG_ERROR1, arg); 1021 SetClassPath(*argv); 1022 argv++; --argc; 1023 } else if (JLI_StrCmp(arg, "-jar") == 0) { 1024 ARG_CHECK (argc, ARG_ERROR2, arg); 1025 jarflag = JNI_TRUE; 1026 } else if (JLI_StrCmp(arg, "-help") == 0 || 1027 JLI_StrCmp(arg, "-h") == 0 || 1028 JLI_StrCmp(arg, "-?") == 0) { 1029 printUsage = JNI_TRUE; 1030 return JNI_TRUE; 1031 } else if (JLI_StrCmp(arg, "-version") == 0) { 1032 printVersion = JNI_TRUE; 1033 return JNI_TRUE; 1034 } else if (JLI_StrCmp(arg, "-showversion") == 0) { 1035 showVersion = JNI_TRUE; 1036 } else if (JLI_StrCmp(arg, "-X") == 0) { 1037 printXUsage = JNI_TRUE; 1038 return JNI_TRUE; 1039 /* 1040 * The following case checks for -XshowSettings OR -XshowSetting:SUBOPT. 1041 * In the latter case, any SUBOPT value not recognized will default to "all" 1042 */ 1043 } else if (JLI_StrCmp(arg, "-XshowSettings") == 0 || 1044 JLI_StrCCmp(arg, "-XshowSettings:") == 0) { 1045 showSettings = arg; 1085 sprintf(tmp, "-X%s", arg + 1); /* skip '-' */ 1086 AddOption(tmp, NULL); 1087 } else if (JLI_StrCmp(arg, "-checksource") == 0 || 1088 JLI_StrCmp(arg, "-cs") == 0 || 1089 JLI_StrCmp(arg, "-noasyncgc") == 0) { 1090 /* No longer supported */ 1091 JLI_ReportErrorMessage(ARG_WARN, arg); 1092 } else if (JLI_StrCCmp(arg, "-version:") == 0 || 1093 JLI_StrCmp(arg, "-no-jre-restrict-search") == 0 || 1094 JLI_StrCmp(arg, "-jre-restrict-search") == 0 || 1095 JLI_StrCCmp(arg, "-splash:") == 0) { 1096 ; /* Ignore machine independent options already handled */ 1097 } else if (RemovableOption(arg) ) { 1098 ; /* Do not pass option to vm. */ 1099 } else { 1100 AddOption(arg, NULL); 1101 } 1102 } 1103 1104 if (--argc >= 0) { 1105 if (jarflag) { 1106 *pjarfile = *argv++; 1107 *pclassname = NULL; 1108 } else { 1109 *pjarfile = NULL; 1110 *pclassname = *argv++; 1111 } 1112 *pargc = argc; 1113 *pargv = argv; 1114 } 1115 if (*pjarfile == NULL && *pclassname == NULL) { 1116 *pret = 1; 1117 } 1118 return JNI_TRUE; 1119 } 1120 1121 /* 1122 * Initializes the Java Virtual Machine. Also frees options array when 1123 * finished. 1124 */ 1125 static jboolean 1126 InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn) 1127 { 1128 JavaVMInitArgs args; 1129 jint r; 1130 1131 memset(&args, 0, sizeof(args)); 1132 args.version = JNI_VERSION_1_2; 1133 args.nOptions = numOptions; 1134 args.options = options; 1135 args.ignoreUnrecognized = JNI_FALSE; 1136 1137 if (JLI_IsTraceLauncher()) { 1246 jarray cls; 1247 jarray ary; 1248 int i; 1249 1250 NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String")); 1251 NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0)); 1252 for (i = 0; i < strc; i++) { 1253 jstring str = NewPlatformString(env, *strv++); 1254 NULL_CHECK0(str); 1255 (*env)->SetObjectArrayElement(env, ary, i, str); 1256 (*env)->DeleteLocalRef(env, str); 1257 } 1258 return ary; 1259 } 1260 1261 /* 1262 * Loads a class and verifies that the main class is present and it is ok to 1263 * call it for more details refer to the java implementation. 1264 */ 1265 static jclass 1266 LoadMainClass(JNIEnv *env, jboolean isJar, char *name) 1267 { 1268 jclass cls; 1269 jmethodID mid; 1270 jstring str; 1271 jobject result; 1272 jlong start, end; 1273 1274 if (JLI_IsTraceLauncher()) { 1275 start = CounterGet(); 1276 } 1277 NULL_CHECK0(cls = FindBootStrapClass(env, "sun/launcher/LauncherHelper")); 1278 NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls, "checkAndLoadMain", 1279 "(ZZLjava/lang/String;)Ljava/lang/Object;")); 1280 str = (*env)->NewStringUTF(env, name); 1281 result = (*env)->CallStaticObjectMethod(env, cls, mid, JNI_TRUE, isJar, str); 1282 1283 if (JLI_IsTraceLauncher()) { 1284 end = CounterGet(); 1285 printf("%ld micro seconds to load main class\n", 1286 (long)(jint)Counter2Micros(end-start)); 1287 printf("----_JAVA_LAUNCHER_DEBUG----\n"); 1288 } 1289 1290 return (jclass)result; 1291 } 1292 1293 /* 1294 * For tools, convert command line args thus: 1295 * javac -cp foo:foo/"*" -J-ms32m ... 1296 * java -ms32m -cp JLI_WildcardExpandClasspath(foo:foo/"*") ... 1297 * 1298 * Takes 4 parameters, and returns the populated arguments 1299 */ 1300 static void 1301 TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv) 1407 for (i = 0; i < cpathc; i++) { 1408 JLI_StrCat(appcp, home); /* c:\program files\myapp */ 1409 JLI_StrCat(appcp, cpathv[i]); /* \lib\myapp.jar */ 1410 JLI_StrCat(appcp, separator); /* ; */ 1411 } 1412 appcp[JLI_StrLen(appcp)-1] = '\0'; /* remove trailing path separator */ 1413 AddOption(appcp, NULL); 1414 return JNI_TRUE; 1415 } 1416 1417 /* 1418 * inject the -Dsun.java.command pseudo property into the args structure 1419 * this pseudo property is used in the HotSpot VM to expose the 1420 * Java class name and arguments to the main method to the VM. The 1421 * HotSpot VM uses this pseudo property to store the Java class name 1422 * (or jar file name) and the arguments to the class's main method 1423 * to the instrumentation memory region. The sun.java.command pseudo 1424 * property is not exported by HotSpot to the Java layer. 1425 */ 1426 void 1427 SetJavaCommandLineProp(char *classname, char *jarfile, 1428 int argc, char **argv) 1429 { 1430 1431 int i = 0; 1432 size_t len = 0; 1433 char* javaCommand = NULL; 1434 char* dashDstr = "-Dsun.java.command="; 1435 1436 if (classname == NULL && jarfile == NULL) { 1437 /* unexpected, one of these should be set. just return without 1438 * setting the property 1439 */ 1440 return; 1441 } 1442 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 1449 * the individual components will be space separated 1450 */ 1451 len = JLI_StrLen(classname); 1452 for (i = 0; i < argc; i++) { 1453 len += JLI_StrLen(argv[i]) + 1; 1454 } 1455 1456 /* allocate the memory */ 1457 javaCommand = (char*) JLI_MemAlloc(len + JLI_StrLen(dashDstr) + 1); 1458 1459 /* build the -D string */ 1460 *javaCommand = '\0'; 1461 JLI_StrCat(javaCommand, dashDstr); 1462 JLI_StrCat(javaCommand, classname); 1463 1464 for (i = 0; i < argc; i++) { 1465 /* the components of the string are space separated. In 1466 * the case of embedded white space, the relationship of 1467 * the white space separated components to their true 1468 * positional arguments will be ambiguous. This issue may 1469 * be addressed in a future release. 1470 */ 1471 JLI_StrCat(javaCommand, " "); 1472 JLI_StrCat(javaCommand, argv[i]); 1473 } 1474 1475 AddOption(javaCommand, NULL); 1476 } 1477 1478 /* 1479 * 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. 1481 */ 1482 void SetJavaLauncherProp() { 1483 AddOption("-Dsun.java.launcher=SUN_STANDARD", NULL); 1484 } 1485 1486 /* 1487 * Prints the version information from the java.version and other properties. 1488 */ 1489 static void 1490 PrintJavaVersion(JNIEnv *env, jboolean extraLF) 1491 { 1492 jclass ver; 1493 jmethodID print; 1494 1495 NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version")); 1496 NULL_CHECK(print = (*env)->GetStaticMethodID(env, 1497 ver, 1498 (extraLF == JNI_TRUE) ? "println" : "print", 1499 "()V" 1500 ) 1501 ); 1502 1896 1897 jint 1898 GetErgoPolicy() 1899 { 1900 return _ergo_policy; 1901 } 1902 1903 jboolean 1904 IsJavaArgs() 1905 { 1906 return _is_java_args; 1907 } 1908 1909 static jboolean 1910 IsWildCardEnabled() 1911 { 1912 return _wc_enabled; 1913 } 1914 1915 static int 1916 ContinueInNewThread(InvocationFunctions* ifn, int argc, 1917 char **argv, char *jarfile, char *classname, int ret) 1918 { 1919 1920 /* 1921 * 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 1923 * return its default stack size through the init args structure. 1924 */ 1925 if (threadStackSize == 0) { 1926 struct JDK1_1InitArgs args1_1; 1927 memset((void*)&args1_1, 0, sizeof(args1_1)); 1928 args1_1.version = JNI_VERSION_1_1; 1929 ifn->GetDefaultJavaVMInitArgs(&args1_1); /* ignore return value */ 1930 if (args1_1.javaStackSize > 0) { 1931 threadStackSize = args1_1.javaStackSize; 1932 } 1933 } 1934 1935 { /* Create a new thread to create JVM and invoke main method */ 1936 JavaMainArgs args; 1937 int rslt; 1938 1939 args.argc = argc; 1940 args.argv = argv; 1941 args.jarfile = jarfile; 1942 args.classname = classname; 1943 args.ifn = *ifn; 1944 1945 rslt = ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args); 1946 /* If the caller has deemed there is an error we 1947 * simply return that, otherwise we return the value of 1948 * the callee 1949 */ 1950 return (ret != 0) ? ret : rslt; 1951 } 1952 } 1953 1954 static void 1955 DumpState() 1956 { 1957 if (!JLI_IsTraceLauncher()) return ; 1958 printf("Launcher state:\n"); 1959 printf("\tdebug:%s\n", (JLI_IsTraceLauncher() == JNI_TRUE) ? "on" : "off"); 1960 printf("\tjavargs:%s\n", (_is_java_args == JNI_TRUE) ? "on" : "off"); 1961 printf("\tprogram name:%s\n", GetProgramName()); 1962 printf("\tlauncher name:%s\n", GetLauncherName()); | 77 78 /* 79 * Entries for splash screen environment variables. 80 * putenv is performed in SelectVersion. We need 81 * them in memory until UnsetEnv, so they are made static 82 * global instead of auto local. 83 */ 84 static char* splash_file_entry = NULL; 85 static char* splash_jar_entry = NULL; 86 87 /* 88 * List of VM options to be specified when the VM is created. 89 */ 90 static JavaVMOption *options; 91 static int numOptions, maxOptions; 92 93 /* 94 * Prototypes for functions internal to launcher. 95 */ 96 static void SetClassPath(const char *s); 97 static void SelectVersion(int argc, char **argv, char **main_class); 98 static jboolean ParseArguments(int *pargc, char ***pargv, 99 int *pmode, char **pwhat, 100 int *pret, const char *jrepath); 101 static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv, 102 InvocationFunctions *ifn); 103 static jstring NewPlatformString(JNIEnv *env, char *s); 104 static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc); 105 static jclass LoadMainClass(JNIEnv *env, int mode, char *name); 106 107 static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv); 108 static jboolean AddApplicationOptions(int cpathc, const char **cpathv); 109 static void SetApplicationClassPath(const char**); 110 111 static void PrintJavaVersion(JNIEnv *env, jboolean extraLF); 112 static void PrintUsage(JNIEnv* env, jboolean doXUsage); 113 static void ShowSettings(JNIEnv* env, char *optString); 114 115 static void SetPaths(int argc, char **argv); 116 117 static void DumpState(); 118 static jboolean RemovableOption(char *option); 119 120 /* Maximum supported entries from jvm.cfg. */ 121 #define INIT_MAX_KNOWN_VMS 10 122 123 /* Values for vmdesc.flag */ 124 enum vmdesc_flag { 125 VM_UNKNOWN = -1, 147 static void ShowSplashScreen(); 148 static jboolean IsWildCardEnabled(); 149 150 #define ARG_CHECK(n, f, a) if (n < 1) { \ 151 JLI_ReportErrorMessage(f, a); \ 152 printUsage = JNI_TRUE; \ 153 *pret = 1; \ 154 return JNI_TRUE; \ 155 } 156 157 /* 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. 160 */ 161 static jlong threadStackSize = 0; /* stack size of the new thread */ 162 static jlong maxHeapSize = 0; /* max heap size */ 163 static jlong initialHeapSize = 0; /* inital heap size */ 164 165 int JNICALL JavaMain(void * args); /* entry point */ 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 176 typedef struct { 177 int argc; 178 char **argv; 179 int mode; 180 char *what; 181 InvocationFunctions ifn; 182 } JavaMainArgs; 183 184 /* 185 * Entry point. 186 */ 187 int 188 JLI_Launch(int argc, char ** argv, /* main argc, argc */ 189 int jargc, const char** jargv, /* java args */ 190 int appclassc, const char** appclassv, /* app classpath */ 191 const char* fullversion, /* full version defined */ 192 const char* dotversion, /* dot version defined */ 193 const char* pname, /* program name */ 194 const char* lname, /* launcher name */ 195 jboolean javaargs, /* JAVA_ARGS */ 196 jboolean cpwildcard, /* classpath wildcard*/ 197 jboolean javaw, /* windows-only javaw */ 198 jint ergo /* ergonomics class policy */ 199 ) 200 { 201 int mode = LM_UNKNOWN; 202 char *what = NULL; 203 char *cpath = 0; 204 char *main_class = NULL; 205 int ret; 206 InvocationFunctions ifn; 207 jlong start, end; 208 char jvmpath[MAXPATHLEN]; 209 char jrepath[MAXPATHLEN]; 210 211 _fVersion = fullversion; 212 _dVersion = dotversion; 213 _launcher_name = lname; 214 _program_name = pname; 215 _is_java_args = javaargs; 216 _wc_enabled = cpwildcard; 217 _ergo_policy = ergo; 218 219 InitLauncher(javaw); 220 DumpState(); 221 222 /* 269 (long)(jint)Counter2Micros(end-start)); 270 271 ++argv; 272 --argc; 273 274 if (IsJavaArgs()) { 275 /* Preprocess wrapper arguments */ 276 TranslateApplicationArgs(jargc, jargv, &argc, &argv); 277 if (!AddApplicationOptions(appclassc, appclassv)) { 278 return(1); 279 } 280 } else { 281 /* Set default CLASSPATH */ 282 cpath = getenv("CLASSPATH"); 283 if (cpath == NULL) { 284 cpath = "."; 285 } 286 SetClassPath(cpath); 287 } 288 289 /* Parse command line options; if the return value of 290 * ParseArguments is false, the program should exit. 291 */ 292 if (!ParseArguments(&argc, &argv, &mode, &what, &ret, jrepath)) 293 { 294 return(ret); 295 } 296 297 /* Override class path if -jar flag was specified */ 298 if (mode == LM_JAR) { 299 SetClassPath(what); /* Override class path */ 300 } 301 302 /* set the -Dsun.java.command pseudo property */ 303 SetJavaCommandLineProp(what, argc, argv); 304 305 /* Set the -Dsun.java.launcher pseudo property */ 306 SetJavaLauncherProp(); 307 308 /* set the -Dsun.java.launcher.* platform properties */ 309 SetJavaLauncherPlatformProps(); 310 311 /* Show the splash screen if needed */ 312 ShowSplashScreen(); 313 314 return ContinueInNewThread(&ifn, argc, argv, mode, what, ret); 315 316 } 317 /* 318 * Always detach the main thread so that it appears to have ended when 319 * the application's main method exits. This will invoke the 320 * uncaught exception handler machinery if main threw an 321 * exception. An uncaught exception handler cannot change the 322 * launcher's return code except by calling System.exit. 323 * 324 * Wait for all non-daemon threads to end, then destroy the VM. 325 * This will actually create a trivial new Java waiter thread 326 * named "DestroyJavaVM", but this will be seen as a different 327 * thread from the one that executed main, even though they are 328 * the same C thread. This allows mainThread.join() and 329 * mainThread.isAlive() to work as expected. 330 */ 331 #define LEAVE() \ 332 if ((*vm)->DetachCurrentThread(vm) != 0) { \ 333 JLI_ReportErrorMessage(JVM_ERROR2); \ 334 ret = 1; \ 342 LEAVE(); \ 343 } \ 344 if ((e) == NULL) { \ 345 JLI_ReportErrorMessage(JNI_ERROR); \ 346 LEAVE(); \ 347 } 348 349 #define CHECK_EXCEPTION_LEAVE(rv) \ 350 if ((*env)->ExceptionOccurred(env)) { \ 351 JLI_ReportExceptionDescription(env); \ 352 ret = (rv); \ 353 LEAVE(); \ 354 } 355 356 int JNICALL 357 JavaMain(void * _args) 358 { 359 JavaMainArgs *args = (JavaMainArgs *)_args; 360 int argc = args->argc; 361 char **argv = args->argv; 362 int mode = args->mode; 363 char *what = args->what; 364 InvocationFunctions ifn = args->ifn; 365 366 JavaVM *vm = 0; 367 JNIEnv *env = 0; 368 jclass mainClass = NULL; 369 jmethodID mainID; 370 jobjectArray mainArgs; 371 int ret = 0; 372 jlong start, end; 373 374 /* Initialize the virtual machine */ 375 start = CounterGet(); 376 if (!InitializeJVM(&vm, &env, &ifn)) { 377 JLI_ReportErrorMessage(JVM_ERROR1); 378 exit(1); 379 } 380 381 if (printVersion || showVersion) { 382 PrintJavaVersion(env, showVersion); 383 CHECK_EXCEPTION_LEAVE(0); 384 if (printVersion) { 385 LEAVE(); 386 } 387 } 388 389 if (showSettings != NULL) { 390 ShowSettings(env, showSettings); 391 CHECK_EXCEPTION_LEAVE(1); 392 } 393 /* If the user specified neither a class name nor a JAR file */ 394 if (printXUsage || printUsage || what == 0 || mode == LM_UNKNOWN) { 395 PrintUsage(env, printXUsage); 396 CHECK_EXCEPTION_LEAVE(1); 397 LEAVE(); 398 } 399 400 FreeKnownVMs(); /* after last possible PrintUsage() */ 401 402 if (JLI_IsTraceLauncher()) { 403 end = CounterGet(); 404 JLI_TraceLauncher("%ld micro seconds to InitializeJVM\n", 405 (long)(jint)Counter2Micros(end-start)); 406 } 407 408 /* At this stage, argc/argv have the application's arguments */ 409 if (JLI_IsTraceLauncher()){ 410 int i; 411 printf("%s is '%s'\n", launchModeNames[mode], what); 412 printf("App's argc is %d\n", argc); 413 for (i=0; i < argc; i++) { 414 printf(" argv[%2d] = '%s'\n", i, argv[i]); 415 } 416 } 417 418 ret = 1; 419 420 /* 421 * Get the application's main class. 422 * 423 * See bugid 5030265. The Main-Class name has already been parsed 424 * from the manifest, but not parsed properly for UTF-8 support. 425 * Hence the code here ignores the value previously extracted and 426 * uses the pre-existing code to reextract the value. This is 427 * possibly an end of release cycle expedient. However, it has 428 * also been discovered that passing some character sets through 429 * the environment has "strange" behavior on some variants of 430 * Windows. Hence, maybe the manifest parsing code local to the 431 * launcher should never be enhanced. 432 * 433 * Hence, future work should either: 434 * 1) Correct the local parsing code and verify that the 435 * Main-Class attribute gets properly passed through 436 * all environments, 437 * 2) Remove the vestages of maintaining main_class through 438 * the environment (and remove these comments). 439 */ 440 mainClass = LoadMainClass(env, mode, what); 441 CHECK_EXCEPTION_NULL_LEAVE(mainClass); 442 443 /* 444 * The LoadMainClass not only loads the main class, it will also ensure 445 * that the main method's signature is correct, therefore further checking 446 * is not required. The main method is invoked here so that extraneous java 447 * stacks are not in the application stack trace. 448 */ 449 mainID = (*env)->GetStaticMethodID(env, mainClass, "main", 450 "([Ljava/lang/String;)V"); 451 CHECK_EXCEPTION_NULL_LEAVE(mainID); 452 453 /* Build argument array */ 454 mainArgs = NewPlatformStringArray(env, argv, argc); 455 CHECK_EXCEPTION_NULL_LEAVE(mainArgs); 456 457 /* Invoke main method. */ 458 (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); 459 460 /* 704 } 705 } 706 707 static void 708 SetClassPath(const char *s) 709 { 710 char *def; 711 const char *orig = s; 712 static const char format[] = "-Djava.class.path=%s"; 713 s = JLI_WildcardExpandClasspath(s); 714 def = JLI_MemAlloc(sizeof(format) 715 - 2 /* strlen("%s") */ 716 + JLI_StrLen(s)); 717 sprintf(def, format, s); 718 AddOption(def, NULL); 719 if (s != orig) 720 JLI_MemFree((char *) s); 721 } 722 723 /* 724 * The SelectVersion() routine ensures that an appropriate version of 725 * the JRE is running. The specification for the appropriate version 726 * is obtained from either the manifest of a jar file (preferred) or 727 * from command line options. 728 * The routine also parses splash screen command line options and 729 * passes on their values in private environment variables. 730 */ 731 static void 732 SelectVersion(int argc, char **argv, char **main_class) 733 { 734 char *arg; 735 char **new_argv; 736 char **new_argp; 737 char *operand; 738 char *version = NULL; 739 char *jre = NULL; 740 int jarflag = 0; 741 int headlessflag = 0; 742 int restrict_search = -1; /* -1 implies not known */ 743 manifest_info info; 951 (void)JLI_StrCat(env_entry, info.main_class); 952 } else { 953 JLI_ReportErrorMessage(CLS_ERROR5, MAXNAMELEN); 954 exit(1); 955 } 956 } 957 (void)putenv(env_entry); 958 ExecJRE(jre, new_argv); 959 JLI_FreeManifest(); 960 JLI_MemFree(new_argv); 961 return; 962 } 963 964 /* 965 * Parses command line arguments. Returns JNI_FALSE if launcher 966 * should exit without starting vm, returns JNI_TRUE if vm needs 967 * to be started to process given options. *pret (the launcher 968 * process return value) is set to 0 for a normal exit. 969 */ 970 static jboolean 971 ParseArguments(int *pargc, char ***pargv, 972 int *pmode, char **pwhat, 973 int *pret, const char *jrepath) 974 { 975 int argc = *pargc; 976 char **argv = *pargv; 977 int mode = LM_UNKNOWN; 978 char *arg; 979 980 *pret = 0; 981 982 while ((arg = *argv) != 0 && *arg == '-') { 983 argv++; --argc; 984 if (JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) { 985 ARG_CHECK (argc, ARG_ERROR1, arg); 986 SetClassPath(*argv); 987 mode = LM_CLASS; 988 argv++; --argc; 989 } else if (JLI_StrCmp(arg, "-jar") == 0) { 990 ARG_CHECK (argc, ARG_ERROR2, arg); 991 mode = LM_JAR; 992 } else if (JLI_StrCmp(arg, "-help") == 0 || 993 JLI_StrCmp(arg, "-h") == 0 || 994 JLI_StrCmp(arg, "-?") == 0) { 995 printUsage = JNI_TRUE; 996 return JNI_TRUE; 997 } else if (JLI_StrCmp(arg, "-version") == 0) { 998 printVersion = JNI_TRUE; 999 return JNI_TRUE; 1000 } else if (JLI_StrCmp(arg, "-showversion") == 0) { 1001 showVersion = JNI_TRUE; 1002 } else if (JLI_StrCmp(arg, "-X") == 0) { 1003 printXUsage = JNI_TRUE; 1004 return JNI_TRUE; 1005 /* 1006 * The following case checks for -XshowSettings OR -XshowSetting:SUBOPT. 1007 * In the latter case, any SUBOPT value not recognized will default to "all" 1008 */ 1009 } else if (JLI_StrCmp(arg, "-XshowSettings") == 0 || 1010 JLI_StrCCmp(arg, "-XshowSettings:") == 0) { 1011 showSettings = arg; 1051 sprintf(tmp, "-X%s", arg + 1); /* skip '-' */ 1052 AddOption(tmp, NULL); 1053 } else if (JLI_StrCmp(arg, "-checksource") == 0 || 1054 JLI_StrCmp(arg, "-cs") == 0 || 1055 JLI_StrCmp(arg, "-noasyncgc") == 0) { 1056 /* No longer supported */ 1057 JLI_ReportErrorMessage(ARG_WARN, arg); 1058 } else if (JLI_StrCCmp(arg, "-version:") == 0 || 1059 JLI_StrCmp(arg, "-no-jre-restrict-search") == 0 || 1060 JLI_StrCmp(arg, "-jre-restrict-search") == 0 || 1061 JLI_StrCCmp(arg, "-splash:") == 0) { 1062 ; /* Ignore machine independent options already handled */ 1063 } else if (RemovableOption(arg) ) { 1064 ; /* Do not pass option to vm. */ 1065 } else { 1066 AddOption(arg, NULL); 1067 } 1068 } 1069 1070 if (--argc >= 0) { 1071 *pwhat = *argv++; 1072 } 1073 1074 if (*pwhat == NULL) { 1075 *pret = 1; 1076 } else if (mode == LM_UNKNOWN) { 1077 /* default to LM_CLASS if -jar and -cp option are 1078 * not specified */ 1079 mode = LM_CLASS; 1080 } 1081 1082 if (argc >= 0) { 1083 *pargc = argc; 1084 *pargv = argv; 1085 } 1086 1087 *pmode = mode; 1088 1089 return JNI_TRUE; 1090 } 1091 1092 /* 1093 * Initializes the Java Virtual Machine. Also frees options array when 1094 * finished. 1095 */ 1096 static jboolean 1097 InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn) 1098 { 1099 JavaVMInitArgs args; 1100 jint r; 1101 1102 memset(&args, 0, sizeof(args)); 1103 args.version = JNI_VERSION_1_2; 1104 args.nOptions = numOptions; 1105 args.options = options; 1106 args.ignoreUnrecognized = JNI_FALSE; 1107 1108 if (JLI_IsTraceLauncher()) { 1217 jarray cls; 1218 jarray ary; 1219 int i; 1220 1221 NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String")); 1222 NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0)); 1223 for (i = 0; i < strc; i++) { 1224 jstring str = NewPlatformString(env, *strv++); 1225 NULL_CHECK0(str); 1226 (*env)->SetObjectArrayElement(env, ary, i, str); 1227 (*env)->DeleteLocalRef(env, str); 1228 } 1229 return ary; 1230 } 1231 1232 /* 1233 * Loads a class and verifies that the main class is present and it is ok to 1234 * call it for more details refer to the java implementation. 1235 */ 1236 static jclass 1237 LoadMainClass(JNIEnv *env, int mode, char *name) 1238 { 1239 jclass cls; 1240 jmethodID mid; 1241 jstring str; 1242 jobject result; 1243 jlong start, end; 1244 1245 if (JLI_IsTraceLauncher()) { 1246 start = CounterGet(); 1247 } 1248 NULL_CHECK0(cls = FindBootStrapClass(env, "sun/launcher/LauncherHelper")); 1249 NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls, "checkAndLoadMain", 1250 "(ZILjava/lang/String;)Ljava/lang/Class;")); 1251 str = (*env)->NewStringUTF(env, name); 1252 result = (*env)->CallStaticObjectMethod(env, cls, mid, JNI_TRUE, mode, str); 1253 1254 if (JLI_IsTraceLauncher()) { 1255 end = CounterGet(); 1256 printf("%ld micro seconds to load main class\n", 1257 (long)(jint)Counter2Micros(end-start)); 1258 printf("----_JAVA_LAUNCHER_DEBUG----\n"); 1259 } 1260 1261 return (jclass)result; 1262 } 1263 1264 /* 1265 * For tools, convert command line args thus: 1266 * javac -cp foo:foo/"*" -J-ms32m ... 1267 * java -ms32m -cp JLI_WildcardExpandClasspath(foo:foo/"*") ... 1268 * 1269 * Takes 4 parameters, and returns the populated arguments 1270 */ 1271 static void 1272 TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv) 1378 for (i = 0; i < cpathc; i++) { 1379 JLI_StrCat(appcp, home); /* c:\program files\myapp */ 1380 JLI_StrCat(appcp, cpathv[i]); /* \lib\myapp.jar */ 1381 JLI_StrCat(appcp, separator); /* ; */ 1382 } 1383 appcp[JLI_StrLen(appcp)-1] = '\0'; /* remove trailing path separator */ 1384 AddOption(appcp, NULL); 1385 return JNI_TRUE; 1386 } 1387 1388 /* 1389 * inject the -Dsun.java.command pseudo property into the args structure 1390 * this pseudo property is used in the HotSpot VM to expose the 1391 * Java class name and arguments to the main method to the VM. The 1392 * HotSpot VM uses this pseudo property to store the Java class name 1393 * (or jar file name) and the arguments to the class's main method 1394 * to the instrumentation memory region. The sun.java.command pseudo 1395 * property is not exported by HotSpot to the Java layer. 1396 */ 1397 void 1398 SetJavaCommandLineProp(char *what, int argc, char **argv) 1399 { 1400 1401 int i = 0; 1402 size_t len = 0; 1403 char* javaCommand = NULL; 1404 char* dashDstr = "-Dsun.java.command="; 1405 1406 if (what == NULL) { 1407 /* unexpected, one of these should be set. just return without 1408 * setting the property 1409 */ 1410 return; 1411 } 1412 1413 /* determine the amount of memory to allocate assuming 1414 * the individual components will be space separated 1415 */ 1416 len = JLI_StrLen(what); 1417 for (i = 0; i < argc; i++) { 1418 len += JLI_StrLen(argv[i]) + 1; 1419 } 1420 1421 /* allocate the memory */ 1422 javaCommand = (char*) JLI_MemAlloc(len + JLI_StrLen(dashDstr) + 1); 1423 1424 /* build the -D string */ 1425 *javaCommand = '\0'; 1426 JLI_StrCat(javaCommand, dashDstr); 1427 JLI_StrCat(javaCommand, what); 1428 1429 for (i = 0; i < argc; i++) { 1430 /* the components of the string are space separated. In 1431 * the case of embedded white space, the relationship of 1432 * the white space separated components to their true 1433 * positional arguments will be ambiguous. This issue may 1434 * be addressed in a future release. 1435 */ 1436 JLI_StrCat(javaCommand, " "); 1437 JLI_StrCat(javaCommand, argv[i]); 1438 } 1439 1440 AddOption(javaCommand, NULL); 1441 } 1442 1443 /* 1444 * JVM would like to know if it's created by a standard Sun launcher, or by 1445 * user native application, the following property indicates the former. 1446 */ 1447 void 1448 SetJavaLauncherProp() { 1449 AddOption("-Dsun.java.launcher=SUN_STANDARD", NULL); 1450 } 1451 1452 /* 1453 * Prints the version information from the java.version and other properties. 1454 */ 1455 static void 1456 PrintJavaVersion(JNIEnv *env, jboolean extraLF) 1457 { 1458 jclass ver; 1459 jmethodID print; 1460 1461 NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version")); 1462 NULL_CHECK(print = (*env)->GetStaticMethodID(env, 1463 ver, 1464 (extraLF == JNI_TRUE) ? "println" : "print", 1465 "()V" 1466 ) 1467 ); 1468 1862 1863 jint 1864 GetErgoPolicy() 1865 { 1866 return _ergo_policy; 1867 } 1868 1869 jboolean 1870 IsJavaArgs() 1871 { 1872 return _is_java_args; 1873 } 1874 1875 static jboolean 1876 IsWildCardEnabled() 1877 { 1878 return _wc_enabled; 1879 } 1880 1881 static int 1882 ContinueInNewThread(InvocationFunctions* ifn, int argc, char **argv, 1883 int mode, char *what, int ret) 1884 { 1885 1886 /* 1887 * If user doesn't specify stack size, check if VM has a preference. 1888 * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will 1889 * return its default stack size through the init args structure. 1890 */ 1891 if (threadStackSize == 0) { 1892 struct JDK1_1InitArgs args1_1; 1893 memset((void*)&args1_1, 0, sizeof(args1_1)); 1894 args1_1.version = JNI_VERSION_1_1; 1895 ifn->GetDefaultJavaVMInitArgs(&args1_1); /* ignore return value */ 1896 if (args1_1.javaStackSize > 0) { 1897 threadStackSize = args1_1.javaStackSize; 1898 } 1899 } 1900 1901 { /* Create a new thread to create JVM and invoke main method */ 1902 JavaMainArgs args; 1903 int rslt; 1904 1905 args.argc = argc; 1906 args.argv = argv; 1907 args.mode = mode; 1908 args.what = what; 1909 args.ifn = *ifn; 1910 1911 rslt = ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args); 1912 /* If the caller has deemed there is an error we 1913 * simply return that, otherwise we return the value of 1914 * the callee 1915 */ 1916 return (ret != 0) ? ret : rslt; 1917 } 1918 } 1919 1920 static void 1921 DumpState() 1922 { 1923 if (!JLI_IsTraceLauncher()) return ; 1924 printf("Launcher state:\n"); 1925 printf("\tdebug:%s\n", (JLI_IsTraceLauncher() == JNI_TRUE) ? "on" : "off"); 1926 printf("\tjavargs:%s\n", (_is_java_args == JNI_TRUE) ? "on" : "off"); 1927 printf("\tprogram name:%s\n", GetProgramName()); 1928 printf("\tlauncher name:%s\n", GetLauncherName()); |