src/share/bin/java.c

Print this page




  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());