src/share/tools/launcher/java.c

Thu, 02 Dec 2010 05:45:54 -0800

author
sla
date
Thu, 02 Dec 2010 05:45:54 -0800
changeset 2327
cb2d0a362639
child 2369
aa6e219afbf1
permissions
-rw-r--r--

6981484: Update development launcher
Summary: Add new development launcher called hotspot(.exe)
Reviewed-by: coleenp

     1 /*
     2  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 /*
    26  * Gamma (Hotspot internal engineering test) launcher based on 6.0u22 JDK,
    27  * search "GAMMA" for gamma specific changes.
    28  *
    29  * GAMMA: gamma launcher is much simpler than regular java launcher in that
    30  *        JVM is either statically linked in or it is installed in the
    31  *        same directory where the launcher exists, so we don't have to
    32  *        worry about choosing the right JVM based on command line flag, jar
    33  *        file and/or ergonomics. Intead of removing unused logic from source
    34  *        they are commented out with #ifndef GAMMA, hopefully it'll be easier
    35  *        to maintain this file in sync with regular JDK launcher.
    36  */
    38 /*
    39  * Shared source for 'java' command line tool.
    40  *
    41  * If JAVA_ARGS is defined, then acts as a launcher for applications. For
    42  * instance, the JDK command line tools such as javac and javadoc (see
    43  * makefiles for more details) are built with this program.  Any arguments
    44  * prefixed with '-J' will be passed directly to the 'java' command.
    45  */
    47 #ifdef GAMMA
    48 #  ifdef JAVA_ARGS
    49 #    error Do NOT define JAVA_ARGS when building gamma launcher
    50 #  endif
    51 #  if !defined(LINK_INTO_AOUT) && !defined(LINK_INTO_LIBJVM)
    52 #    error Either LINK_INTO_AOUT or LINK_INTO_LIBJVM must be defined
    53 #  endif
    54 #endif
    56 /*
    57  * One job of the launcher is to remove command line options which the
    58  * vm does not understand and will not process.  These options include
    59  * options which select which style of vm is run (e.g. -client and
    60  * -server) as well as options which select the data model to use.
    61  * Additionally, for tools which invoke an underlying vm "-J-foo"
    62  * options are turned into "-foo" options to the vm.  This option
    63  * filtering is handled in a number of places in the launcher, some of
    64  * it in machine-dependent code.  In this file, the function
    65  * CheckJVMType removes vm style options and TranslateApplicationArgs
    66  * removes "-J" prefixes.  On unix platforms, the
    67  * CreateExecutionEnvironment function from the unix java_md.c file
    68  * processes and removes -d<n> options.  However, in case
    69  * CreateExecutionEnvironment does not need to exec because
    70  * LD_LIBRARY_PATH is set acceptably and the data model does not need
    71  * to be changed, ParseArguments will screen out the redundant -d<n>
    72  * options and prevent them from being passed to the vm; this is done
    73  * by using the machine-dependent call
    74  * RemovableMachineDependentOption.
    75  */
    77 #include <stdio.h>
    78 #include <stdlib.h>
    79 #include <string.h>
    81 #include <jni.h>
    82 #include <jvm.h>
    83 #include "java.h"
    84 #ifndef GAMMA
    85 #include "manifest_info.h"
    86 #include "version_comp.h"
    87 #include "splashscreen.h"
    88 #endif
    89 #include "wildcard.h"
    91 #ifndef FULL_VERSION
    92 #define FULL_VERSION JDK_MAJOR_VERSION "." JDK_MINOR_VERSION
    93 #endif
    95 /*
    96  * The following environment variable is used to influence the behavior
    97  * of the jre exec'd through the SelectVersion routine.  The command line
    98  * options which specify the version are not passed to the exec'd version,
    99  * because that jre may be an older version which wouldn't recognize them.
   100  * This environment variable is known to this (and later) version and serves
   101  * to suppress the version selection code.  This is not only for efficiency,
   102  * but also for correctness, since any command line options have been
   103  * removed which would cause any value found in the manifest to be used.
   104  * This would be incorrect because the command line options are defined
   105  * to take precedence.
   106  *
   107  * The value associated with this environment variable is the MainClass
   108  * name from within the executable jar file (if any). This is strictly a
   109  * performance enhancement to avoid re-reading the jar file manifest.
   110  *
   111  * A NOTE TO DEVELOPERS: For performance reasons it is important that
   112  * the program image remain relatively small until after SelectVersion
   113  * CreateExecutionEnvironment have finished their possibly recursive
   114  * processing. Watch everything, but resist all temptations to use Java
   115  * interfaces.
   116  */
   117 #define ENV_ENTRY "_JAVA_VERSION_SET"
   119 #ifndef GAMMA
   120 #define SPLASH_FILE_ENV_ENTRY "_JAVA_SPLASH_FILE"
   121 #define SPLASH_JAR_ENV_ENTRY "_JAVA_SPLASH_JAR"
   122 #endif
   124 static jboolean printVersion = JNI_FALSE; /* print and exit */
   125 static jboolean showVersion = JNI_FALSE;  /* print but continue */
   126 static char *progname;
   127 jboolean _launcher_debug = JNI_FALSE;
   129 #ifndef GAMMA
   130 /*
   131  * Entries for splash screen environment variables.
   132  * putenv is performed in SelectVersion. We need
   133  * them in memory until UnsetEnv, so they are made static
   134  * global instead of auto local.
   135  */
   136 static char* splash_file_entry = NULL;
   137 static char* splash_jar_entry = NULL;
   138 #endif
   140 /*
   141  * List of VM options to be specified when the VM is created.
   142  */
   143 static JavaVMOption *options;
   144 static int numOptions, maxOptions;
   146 /*
   147  * Prototypes for functions internal to launcher.
   148  */
   149 static void SetClassPath(const char *s);
   150 static void SelectVersion(int argc, char **argv, char **main_class);
   151 static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile,
   152                                char **pclassname, int *pret, const char *jvmpath);
   153 static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
   154                               InvocationFunctions *ifn);
   155 static jstring NewPlatformString(JNIEnv *env, char *s);
   156 static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc);
   157 static jclass LoadClass(JNIEnv *env, char *name);
   158 static jstring GetMainClassName(JNIEnv *env, char *jarname);
   159 static void SetJavaCommandLineProp(char* classname, char* jarfile, int argc, char** argv);
   160 static void SetJavaLauncherProp(void);
   162 #ifdef JAVA_ARGS
   163 static void TranslateApplicationArgs(int *pargc, char ***pargv);
   164 static jboolean AddApplicationOptions(void);
   165 #endif
   167 static void PrintJavaVersion(JNIEnv *env);
   168 static void PrintUsage(void);
   169 static jint PrintXUsage(const char *jvmpath);
   171 static void SetPaths(int argc, char **argv);
   173 #ifndef GAMMA
   175 /* Maximum supported entries from jvm.cfg. */
   176 #define INIT_MAX_KNOWN_VMS      10
   177 /* Values for vmdesc.flag */
   178 #define VM_UNKNOWN              -1
   179 #define VM_KNOWN                 0
   180 #define VM_ALIASED_TO            1
   181 #define VM_WARN                  2
   182 #define VM_ERROR                 3
   183 #define VM_IF_SERVER_CLASS       4
   184 #define VM_IGNORE                5
   185 struct vmdesc {
   186     char *name;
   187     int flag;
   188     char *alias;
   189     char *server_class;
   190 };
   191 static struct vmdesc *knownVMs = NULL;
   192 static int knownVMsCount = 0;
   193 static int knownVMsLimit = 0;
   195 static void GrowKnownVMs();
   196 static int  KnownVMIndex(const char* name);
   197 static void FreeKnownVMs();
   198 static void ShowSplashScreen();
   200 #endif /* ifndef GAMMA */
   202 jboolean ServerClassMachine();
   204 /* flag which if set suppresses error messages from the launcher */
   205 static int noExitErrorMessage = 0;
   207 /*
   208  * Running Java code in primordial thread caused many problems. We will
   209  * create a new thread to invoke JVM. See 6316197 for more information.
   210  */
   211 static jlong threadStackSize = 0;  /* stack size of the new thread */
   213 int JNICALL JavaMain(void * args); /* entry point                  */
   215 struct JavaMainArgs {
   216   int     argc;
   217   char ** argv;
   218   char *  jarfile;
   219   char *  classname;
   220   InvocationFunctions ifn;
   221 };
   223 /*
   224  * Entry point.
   225  */
   226 int
   227 main(int argc, char ** argv)
   228 {
   229     char *jarfile = 0;
   230     char *classname = 0;
   231     char *s = 0;
   232     char *main_class = NULL;
   233     int ret;
   234     InvocationFunctions ifn;
   235     jlong start, end;
   236     char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN];
   237     char ** original_argv = argv;
   239     if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) {
   240         _launcher_debug = JNI_TRUE;
   241         printf("----_JAVA_LAUNCHER_DEBUG----\n");
   242     }
   244 #ifndef GAMMA
   245     /*
   246      * Make sure the specified version of the JRE is running.
   247      *
   248      * There are three things to note about the SelectVersion() routine:
   249      *  1) If the version running isn't correct, this routine doesn't
   250      *     return (either the correct version has been exec'd or an error
   251      *     was issued).
   252      *  2) Argc and Argv in this scope are *not* altered by this routine.
   253      *     It is the responsibility of subsequent code to ignore the
   254      *     arguments handled by this routine.
   255      *  3) As a side-effect, the variable "main_class" is guaranteed to
   256      *     be set (if it should ever be set).  This isn't exactly the
   257      *     poster child for structured programming, but it is a small
   258      *     price to pay for not processing a jar file operand twice.
   259      *     (Note: This side effect has been disabled.  See comment on
   260      *     bugid 5030265 below.)
   261      */
   262     SelectVersion(argc, argv, &main_class);
   263 #endif /* ifndef GAMMA */
   265     /* copy original argv */
   266     {
   267       int i;
   268       original_argv = (char**)JLI_MemAlloc(sizeof(char*)*(argc+1));
   269       for(i = 0; i < argc+1; i++)
   270         original_argv[i] = argv[i];
   271     }
   273     CreateExecutionEnvironment(&argc, &argv,
   274                                jrepath, sizeof(jrepath),
   275                                jvmpath, sizeof(jvmpath),
   276                                original_argv);
   278     ifn.CreateJavaVM = 0;
   279     ifn.GetDefaultJavaVMInitArgs = 0;
   281     if (_launcher_debug)
   282       start = CounterGet();
   283     if (!LoadJavaVM(jvmpath, &ifn)) {
   284       exit(6);
   285     }
   286     if (_launcher_debug) {
   287       end   = CounterGet();
   288       printf("%ld micro seconds to LoadJavaVM\n",
   289              (long)(jint)Counter2Micros(end-start));
   290     }
   292 #ifdef JAVA_ARGS  /* javac, jar and friends. */
   293     progname = "java";
   294 #else             /* java, oldjava, javaw and friends */
   295 #ifdef PROGNAME
   296     progname = PROGNAME;
   297 #else
   298     progname = *argv;
   299     if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) {
   300         progname = s + 1;
   301     }
   302 #endif /* PROGNAME */
   303 #endif /* JAVA_ARGS */
   304     ++argv;
   305     --argc;
   307 #ifdef JAVA_ARGS
   308     /* Preprocess wrapper arguments */
   309     TranslateApplicationArgs(&argc, &argv);
   310     if (!AddApplicationOptions()) {
   311         exit(1);
   312     }
   313 #endif
   315     /* Set default CLASSPATH */
   316     if ((s = getenv("CLASSPATH")) == 0) {
   317         s = ".";
   318     }
   319 #ifndef JAVA_ARGS
   320     SetClassPath(s);
   321 #endif
   323     /*
   324      *  Parse command line options; if the return value of
   325      *  ParseArguments is false, the program should exit.
   326      */
   327     if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret, jvmpath)) {
   328       exit(ret);
   329     }
   331     /* Override class path if -jar flag was specified */
   332     if (jarfile != 0) {
   333         SetClassPath(jarfile);
   334     }
   336     /* set the -Dsun.java.command pseudo property */
   337     SetJavaCommandLineProp(classname, jarfile, argc, argv);
   339     /* Set the -Dsun.java.launcher pseudo property */
   340     SetJavaLauncherProp();
   342     /* set the -Dsun.java.launcher.* platform properties */
   343     SetJavaLauncherPlatformProps();
   345 #ifndef GAMMA
   346     /* Show the splash screen if needed */
   347     ShowSplashScreen();
   348 #endif
   350     /*
   351      * Done with all command line processing and potential re-execs so
   352      * clean up the environment.
   353      */
   354     (void)UnsetEnv(ENV_ENTRY);
   355 #ifndef GAMMA
   356     (void)UnsetEnv(SPLASH_FILE_ENV_ENTRY);
   357     (void)UnsetEnv(SPLASH_JAR_ENV_ENTRY);
   359     JLI_MemFree(splash_jar_entry);
   360     JLI_MemFree(splash_file_entry);
   361 #endif
   363     /*
   364      * If user doesn't specify stack size, check if VM has a preference.
   365      * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will
   366      * return its default stack size through the init args structure.
   367      */
   368     if (threadStackSize == 0) {
   369       struct JDK1_1InitArgs args1_1;
   370       memset((void*)&args1_1, 0, sizeof(args1_1));
   371       args1_1.version = JNI_VERSION_1_1;
   372       ifn.GetDefaultJavaVMInitArgs(&args1_1);  /* ignore return value */
   373       if (args1_1.javaStackSize > 0) {
   374          threadStackSize = args1_1.javaStackSize;
   375       }
   376     }
   378     { /* Create a new thread to create JVM and invoke main method */
   379       struct JavaMainArgs args;
   381       args.argc = argc;
   382       args.argv = argv;
   383       args.jarfile = jarfile;
   384       args.classname = classname;
   385       args.ifn = ifn;
   387       return ContinueInNewThread(JavaMain, threadStackSize, (void*)&args);
   388     }
   389 }
   391 int JNICALL
   392 JavaMain(void * _args)
   393 {
   394     struct JavaMainArgs *args = (struct JavaMainArgs *)_args;
   395     int argc = args->argc;
   396     char **argv = args->argv;
   397     char *jarfile = args->jarfile;
   398     char *classname = args->classname;
   399     InvocationFunctions ifn = args->ifn;
   401     JavaVM *vm = 0;
   402     JNIEnv *env = 0;
   403     jstring mainClassName;
   404     jclass mainClass;
   405     jmethodID mainID;
   406     jobjectArray mainArgs;
   407     int ret = 0;
   408     jlong start, end;
   410     /*
   411      * Error message to print or display; by default the message will
   412      * only be displayed in a window.
   413      */
   414     char * message = "Fatal exception occurred.  Program will exit.";
   415     jboolean messageDest = JNI_FALSE;
   417     /* Initialize the virtual machine */
   419     if (_launcher_debug)
   420         start = CounterGet();
   421     if (!InitializeJVM(&vm, &env, &ifn)) {
   422         ReportErrorMessage("Could not create the Java virtual machine.",
   423                            JNI_TRUE);
   424         exit(1);
   425     }
   427     if (printVersion || showVersion) {
   428         PrintJavaVersion(env);
   429         if ((*env)->ExceptionOccurred(env)) {
   430             ReportExceptionDescription(env);
   431             goto leave;
   432         }
   433         if (printVersion) {
   434             ret = 0;
   435             message = NULL;
   436             goto leave;
   437         }
   438         if (showVersion) {
   439             fprintf(stderr, "\n");
   440         }
   441     }
   443     /* If the user specified neither a class name nor a JAR file */
   444     if (jarfile == 0 && classname == 0) {
   445         PrintUsage();
   446         message = NULL;
   447         goto leave;
   448     }
   450 #ifndef GAMMA
   451     FreeKnownVMs();  /* after last possible PrintUsage() */
   452 #endif
   454     if (_launcher_debug) {
   455         end   = CounterGet();
   456         printf("%ld micro seconds to InitializeJVM\n",
   457                (long)(jint)Counter2Micros(end-start));
   458     }
   460     /* At this stage, argc/argv have the applications' arguments */
   461     if (_launcher_debug) {
   462         int i = 0;
   463         printf("Main-Class is '%s'\n", classname ? classname : "");
   464         printf("Apps' argc is %d\n", argc);
   465         for (; i < argc; i++) {
   466             printf("    argv[%2d] = '%s'\n", i, argv[i]);
   467         }
   468     }
   470     ret = 1;
   472     /*
   473      * Get the application's main class.
   474      *
   475      * See bugid 5030265.  The Main-Class name has already been parsed
   476      * from the manifest, but not parsed properly for UTF-8 support.
   477      * Hence the code here ignores the value previously extracted and
   478      * uses the pre-existing code to reextract the value.  This is
   479      * possibly an end of release cycle expedient.  However, it has
   480      * also been discovered that passing some character sets through
   481      * the environment has "strange" behavior on some variants of
   482      * Windows.  Hence, maybe the manifest parsing code local to the
   483      * launcher should never be enhanced.
   484      *
   485      * Hence, future work should either:
   486      *     1)   Correct the local parsing code and verify that the
   487      *          Main-Class attribute gets properly passed through
   488      *          all environments,
   489      *     2)   Remove the vestages of maintaining main_class through
   490      *          the environment (and remove these comments).
   491      */
   492     if (jarfile != 0) {
   493         mainClassName = GetMainClassName(env, jarfile);
   494         if ((*env)->ExceptionOccurred(env)) {
   495             ReportExceptionDescription(env);
   496             goto leave;
   497         }
   498         if (mainClassName == NULL) {
   499           const char * format = "Failed to load Main-Class manifest "
   500                                 "attribute from\n%s";
   501           message = (char*)JLI_MemAlloc((strlen(format) + strlen(jarfile)) *
   502                                     sizeof(char));
   503           sprintf(message, format, jarfile);
   504           messageDest = JNI_TRUE;
   505           goto leave;
   506         }
   507         classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
   508         if (classname == NULL) {
   509             ReportExceptionDescription(env);
   510             goto leave;
   511         }
   512         mainClass = LoadClass(env, classname);
   513         if(mainClass == NULL) { /* exception occured */
   514             const char * format = "Could not find the main class: %s. Program will exit.";
   515             ReportExceptionDescription(env);
   516             message = (char *)JLI_MemAlloc((strlen(format) +
   517                                             strlen(classname)) * sizeof(char) );
   518             messageDest = JNI_TRUE;
   519             sprintf(message, format, classname);
   520             goto leave;
   521         }
   522         (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
   523     } else {
   524       mainClassName = NewPlatformString(env, classname);
   525       if (mainClassName == NULL) {
   526         const char * format = "Failed to load Main Class: %s";
   527         message = (char *)JLI_MemAlloc((strlen(format) + strlen(classname)) *
   528                                    sizeof(char) );
   529         sprintf(message, format, classname);
   530         messageDest = JNI_TRUE;
   531         goto leave;
   532       }
   533       classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
   534       if (classname == NULL) {
   535         ReportExceptionDescription(env);
   536         goto leave;
   537       }
   538       mainClass = LoadClass(env, classname);
   539       if(mainClass == NULL) { /* exception occured */
   540         const char * format = "Could not find the main class: %s.  Program will exit.";
   541         ReportExceptionDescription(env);
   542         message = (char *)JLI_MemAlloc((strlen(format) +
   543                                         strlen(classname)) * sizeof(char) );
   544         messageDest = JNI_TRUE;
   545         sprintf(message, format, classname);
   546         goto leave;
   547       }
   548       (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
   549     }
   551     /* Get the application's main method */
   552     mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
   553                                        "([Ljava/lang/String;)V");
   554     if (mainID == NULL) {
   555         if ((*env)->ExceptionOccurred(env)) {
   556             ReportExceptionDescription(env);
   557         } else {
   558           message = "No main method found in specified class.";
   559           messageDest = JNI_TRUE;
   560         }
   561         goto leave;
   562     }
   564     {    /* Make sure the main method is public */
   565         jint mods;
   566         jmethodID mid;
   567         jobject obj = (*env)->ToReflectedMethod(env, mainClass,
   568                                                 mainID, JNI_TRUE);
   570         if( obj == NULL) { /* exception occurred */
   571             ReportExceptionDescription(env);
   572             goto leave;
   573         }
   575         mid =
   576           (*env)->GetMethodID(env,
   577                               (*env)->GetObjectClass(env, obj),
   578                               "getModifiers", "()I");
   579         if ((*env)->ExceptionOccurred(env)) {
   580             ReportExceptionDescription(env);
   581             goto leave;
   582         }
   584         mods = (*env)->CallIntMethod(env, obj, mid);
   585         if ((mods & 1) == 0) { /* if (!Modifier.isPublic(mods)) ... */
   586             message = "Main method not public.";
   587             messageDest = JNI_TRUE;
   588             goto leave;
   589         }
   590     }
   592     /* Build argument array */
   593     mainArgs = NewPlatformStringArray(env, argv, argc);
   594     if (mainArgs == NULL) {
   595         ReportExceptionDescription(env);
   596         goto leave;
   597     }
   599     /* Invoke main method. */
   600     (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
   602     /*
   603      * The launcher's exit code (in the absence of calls to
   604      * System.exit) will be non-zero if main threw an exception.
   605      */
   606     ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
   608     /*
   609      * Detach the main thread so that it appears to have ended when
   610      * the application's main method exits.  This will invoke the
   611      * uncaught exception handler machinery if main threw an
   612      * exception.  An uncaught exception handler cannot change the
   613      * launcher's return code except by calling System.exit.
   614      */
   615     if ((*vm)->DetachCurrentThread(vm) != 0) {
   616         message = "Could not detach main thread.";
   617         messageDest = JNI_TRUE;
   618         ret = 1;
   619         goto leave;
   620     }
   622     message = NULL;
   624  leave:
   625     /*
   626      * Wait for all non-daemon threads to end, then destroy the VM.
   627      * This will actually create a trivial new Java waiter thread
   628      * named "DestroyJavaVM", but this will be seen as a different
   629      * thread from the one that executed main, even though they are
   630      * the same C thread.  This allows mainThread.join() and
   631      * mainThread.isAlive() to work as expected.
   632      */
   633     (*vm)->DestroyJavaVM(vm);
   635     if(message != NULL && !noExitErrorMessage)
   636       ReportErrorMessage(message, messageDest);
   637     return ret;
   638 }
   640 #ifndef GAMMA
   641 /*
   642  * Checks the command line options to find which JVM type was
   643  * specified.  If no command line option was given for the JVM type,
   644  * the default type is used.  The environment variable
   645  * JDK_ALTERNATE_VM and the command line option -XXaltjvm= are also
   646  * checked as ways of specifying which JVM type to invoke.
   647  */
   648 char *
   649 CheckJvmType(int *pargc, char ***argv, jboolean speculative) {
   650     int i, argi;
   651     int argc;
   652     char **newArgv;
   653     int newArgvIdx = 0;
   654     int isVMType;
   655     int jvmidx = -1;
   656     char *jvmtype = getenv("JDK_ALTERNATE_VM");
   658     argc = *pargc;
   660     /* To make things simpler we always copy the argv array */
   661     newArgv = JLI_MemAlloc((argc + 1) * sizeof(char *));
   663     /* The program name is always present */
   664     newArgv[newArgvIdx++] = (*argv)[0];
   666     for (argi = 1; argi < argc; argi++) {
   667         char *arg = (*argv)[argi];
   668         isVMType = 0;
   670 #ifdef JAVA_ARGS
   671         if (arg[0] != '-') {
   672             newArgv[newArgvIdx++] = arg;
   673             continue;
   674         }
   675 #else
   676         if (strcmp(arg, "-classpath") == 0 ||
   677             strcmp(arg, "-cp") == 0) {
   678             newArgv[newArgvIdx++] = arg;
   679             argi++;
   680             if (argi < argc) {
   681                 newArgv[newArgvIdx++] = (*argv)[argi];
   682             }
   683             continue;
   684         }
   685         if (arg[0] != '-') break;
   686 #endif
   688         /* Did the user pass an explicit VM type? */
   689         i = KnownVMIndex(arg);
   690         if (i >= 0) {
   691             jvmtype = knownVMs[jvmidx = i].name + 1; /* skip the - */
   692             isVMType = 1;
   693             *pargc = *pargc - 1;
   694         }
   696         /* Did the user specify an "alternate" VM? */
   697         else if (strncmp(arg, "-XXaltjvm=", 10) == 0 || strncmp(arg, "-J-XXaltjvm=", 12) == 0) {
   698             isVMType = 1;
   699             jvmtype = arg+((arg[1]=='X')? 10 : 12);
   700             jvmidx = -1;
   701         }
   703         if (!isVMType) {
   704             newArgv[newArgvIdx++] = arg;
   705         }
   706     }
   708     /*
   709      * Finish copying the arguments if we aborted the above loop.
   710      * NOTE that if we aborted via "break" then we did NOT copy the
   711      * last argument above, and in addition argi will be less than
   712      * argc.
   713      */
   714     while (argi < argc) {
   715         newArgv[newArgvIdx++] = (*argv)[argi];
   716         argi++;
   717     }
   719     /* argv is null-terminated */
   720     newArgv[newArgvIdx] = 0;
   722     /* Copy back argv */
   723     *argv = newArgv;
   724     *pargc = newArgvIdx;
   726     /* use the default VM type if not specified (no alias processing) */
   727     if (jvmtype == NULL) {
   728       char* result = knownVMs[0].name+1;
   729       /* Use a different VM type if we are on a server class machine? */
   730       if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) &&
   731           (ServerClassMachine() == JNI_TRUE)) {
   732         result = knownVMs[0].server_class+1;
   733       }
   734       if (_launcher_debug) {
   735         printf("Default VM: %s\n", result);
   736       }
   737       return result;
   738     }
   740     /* if using an alternate VM, no alias processing */
   741     if (jvmidx < 0)
   742       return jvmtype;
   744     /* Resolve aliases first */
   745     {
   746       int loopCount = 0;
   747       while (knownVMs[jvmidx].flag == VM_ALIASED_TO) {
   748         int nextIdx = KnownVMIndex(knownVMs[jvmidx].alias);
   750         if (loopCount > knownVMsCount) {
   751           if (!speculative) {
   752             ReportErrorMessage("Error: Corrupt jvm.cfg file; cycle in alias list.",
   753                                JNI_TRUE);
   754             exit(1);
   755           } else {
   756             return "ERROR";
   757             /* break; */
   758           }
   759         }
   761         if (nextIdx < 0) {
   762           if (!speculative) {
   763             ReportErrorMessage2("Error: Unable to resolve VM alias %s",
   764                                 knownVMs[jvmidx].alias, JNI_TRUE);
   765             exit(1);
   766           } else {
   767             return "ERROR";
   768           }
   769         }
   770         jvmidx = nextIdx;
   771         jvmtype = knownVMs[jvmidx].name+1;
   772         loopCount++;
   773       }
   774     }
   776     switch (knownVMs[jvmidx].flag) {
   777     case VM_WARN:
   778         if (!speculative) {
   779             fprintf(stderr, "Warning: %s VM not supported; %s VM will be used\n",
   780                     jvmtype, knownVMs[0].name + 1);
   781         }
   782         /* fall through */
   783     case VM_IGNORE:
   784         jvmtype = knownVMs[jvmidx=0].name + 1;
   785         /* fall through */
   786     case VM_KNOWN:
   787         break;
   788     case VM_ERROR:
   789         if (!speculative) {
   790             ReportErrorMessage2("Error: %s VM not supported", jvmtype, JNI_TRUE);
   791             exit(1);
   792         } else {
   793             return "ERROR";
   794         }
   795     }
   797     return jvmtype;
   798 }
   799 #endif /* ifndef GAMMA */
   801 # define KB (1024UL)
   802 # define MB (1024UL * KB)
   803 # define GB (1024UL * MB)
   805 /* copied from HotSpot function "atomll()" */
   806 static int
   807 parse_stack_size(const char *s, jlong *result) {
   808   jlong n = 0;
   809   int args_read = sscanf(s, jlong_format_specifier(), &n);
   810   if (args_read != 1) {
   811     return 0;
   812   }
   813   while (*s != '\0' && *s >= '0' && *s <= '9') {
   814     s++;
   815   }
   816   // 4705540: illegal if more characters are found after the first non-digit
   817   if (strlen(s) > 1) {
   818     return 0;
   819   }
   820   switch (*s) {
   821     case 'T': case 't':
   822       *result = n * GB * KB;
   823       return 1;
   824     case 'G': case 'g':
   825       *result = n * GB;
   826       return 1;
   827     case 'M': case 'm':
   828       *result = n * MB;
   829       return 1;
   830     case 'K': case 'k':
   831       *result = n * KB;
   832       return 1;
   833     case '\0':
   834       *result = n;
   835       return 1;
   836     default:
   837       /* Create JVM with default stack and let VM handle malformed -Xss string*/
   838       return 0;
   839   }
   840 }
   842 /*
   843  * Adds a new VM option with the given given name and value.
   844  */
   845 void
   846 AddOption(char *str, void *info)
   847 {
   848     /*
   849      * Expand options array if needed to accommodate at least one more
   850      * VM option.
   851      */
   852     if (numOptions >= maxOptions) {
   853         if (options == 0) {
   854             maxOptions = 4;
   855             options = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption));
   856         } else {
   857             JavaVMOption *tmp;
   858             maxOptions *= 2;
   859             tmp = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption));
   860             memcpy(tmp, options, numOptions * sizeof(JavaVMOption));
   861             JLI_MemFree(options);
   862             options = tmp;
   863         }
   864     }
   865     options[numOptions].optionString = str;
   866     options[numOptions++].extraInfo = info;
   868     if (strncmp(str, "-Xss", 4) == 0) {
   869       jlong tmp;
   870       if (parse_stack_size(str + 4, &tmp)) {
   871         threadStackSize = tmp;
   872       }
   873     }
   874 }
   876 static void
   877 SetClassPath(const char *s)
   878 {
   879     char *def;
   880     s = JLI_WildcardExpandClasspath(s);
   881     def = JLI_MemAlloc(strlen(s) + 40);
   882     sprintf(def, "-Djava.class.path=%s", s);
   883     AddOption(def, NULL);
   884 }
   886 #ifndef GAMMA
   887 /*
   888  * The SelectVersion() routine ensures that an appropriate version of
   889  * the JRE is running.  The specification for the appropriate version
   890  * is obtained from either the manifest of a jar file (preferred) or
   891  * from command line options.
   892  * The routine also parses splash screen command line options and
   893  * passes on their values in private environment variables.
   894  */
   895 static void
   896 SelectVersion(int argc, char **argv, char **main_class)
   897 {
   898     char    *arg;
   899     char    **new_argv;
   900     char    **new_argp;
   901     char    *operand;
   902     char    *version = NULL;
   903     char    *jre = NULL;
   904     int     jarflag = 0;
   905     int     headlessflag = 0;
   906     int     restrict_search = -1;               /* -1 implies not known */
   907     manifest_info info;
   908     char    env_entry[MAXNAMELEN + 24] = ENV_ENTRY "=";
   909     char    *splash_file_name = NULL;
   910     char    *splash_jar_name = NULL;
   911     char    *env_in;
   912     int     res;
   914     /*
   915      * If the version has already been selected, set *main_class
   916      * with the value passed through the environment (if any) and
   917      * simply return.
   918      */
   919     if ((env_in = getenv(ENV_ENTRY)) != NULL) {
   920         if (*env_in != '\0')
   921             *main_class = JLI_StringDup(env_in);
   922         return;
   923     }
   925     /*
   926      * Scan through the arguments for options relevant to multiple JRE
   927      * support.  For reference, the command line syntax is defined as:
   928      *
   929      * SYNOPSIS
   930      *      java [options] class [argument...]
   931      *
   932      *      java [options] -jar file.jar [argument...]
   933      *
   934      * As the scan is performed, make a copy of the argument list with
   935      * the version specification options (new to 1.5) removed, so that
   936      * a version less than 1.5 can be exec'd.
   937      *
   938      * Note that due to the syntax of the native Windows interface
   939      * CreateProcess(), processing similar to the following exists in
   940      * the Windows platform specific routine ExecJRE (in java_md.c).
   941      * Changes here should be reproduced there.
   942      */
   943     new_argv = JLI_MemAlloc((argc + 1) * sizeof(char*));
   944     new_argv[0] = argv[0];
   945     new_argp = &new_argv[1];
   946     argc--;
   947     argv++;
   948     while ((arg = *argv) != 0 && *arg == '-') {
   949         if (strncmp(arg, "-version:", 9) == 0) {
   950             version = arg + 9;
   951         } else if (strcmp(arg, "-jre-restrict-search") == 0) {
   952             restrict_search = 1;
   953         } else if (strcmp(arg, "-no-jre-restrict-search") == 0) {
   954             restrict_search = 0;
   955         } else {
   956             if (strcmp(arg, "-jar") == 0)
   957                 jarflag = 1;
   958             /* deal with "unfortunate" classpath syntax */
   959             if ((strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) &&
   960               (argc >= 2)) {
   961                 *new_argp++ = arg;
   962                 argc--;
   963                 argv++;
   964                 arg = *argv;
   965             }
   967             /*
   968              * Checking for headless toolkit option in the some way as AWT does:
   969              * "true" means true and any other value means false
   970              */
   971             if (strcmp(arg, "-Djava.awt.headless=true") == 0) {
   972                 headlessflag = 1;
   973             } else if (strncmp(arg, "-Djava.awt.headless=", 20) == 0) {
   974                 headlessflag = 0;
   975             } else if (strncmp(arg, "-splash:", 8) == 0) {
   976                 splash_file_name = arg+8;
   977             }
   978             *new_argp++ = arg;
   979         }
   980         argc--;
   981         argv++;
   982     }
   983     if (argc <= 0) {    /* No operand? Possibly legit with -[full]version */
   984         operand = NULL;
   985     } else {
   986         argc--;
   987         *new_argp++ = operand = *argv++;
   988     }
   989     while (argc-- > 0)  /* Copy over [argument...] */
   990         *new_argp++ = *argv++;
   991     *new_argp = NULL;
   993     /*
   994      * If there is a jar file, read the manifest. If the jarfile can't be
   995      * read, the manifest can't be read from the jar file, or the manifest
   996      * is corrupt, issue the appropriate error messages and exit.
   997      *
   998      * Even if there isn't a jar file, construct a manifest_info structure
   999      * containing the command line information.  It's a convenient way to carry
  1000      * this data around.
  1001      */
  1002     if (jarflag && operand) {
  1003         if ((res = JLI_ParseManifest(operand, &info)) != 0) {
  1004             if (res == -1)
  1005                 ReportErrorMessage2("Unable to access jarfile %s",
  1006                   operand, JNI_TRUE);
  1007             else
  1008                 ReportErrorMessage2("Invalid or corrupt jarfile %s",
  1009                   operand, JNI_TRUE);
  1010             exit(1);
  1013         /*
  1014          * Command line splash screen option should have precedence
  1015          * over the manifest, so the manifest data is used only if
  1016          * splash_file_name has not been initialized above during command
  1017          * line parsing
  1018          */
  1019         if (!headlessflag && !splash_file_name && info.splashscreen_image_file_name) {
  1020             splash_file_name = info.splashscreen_image_file_name;
  1021             splash_jar_name = operand;
  1023     } else {
  1024         info.manifest_version = NULL;
  1025         info.main_class = NULL;
  1026         info.jre_version = NULL;
  1027         info.jre_restrict_search = 0;
  1030     /*
  1031      * Passing on splash screen info in environment variables
  1032      */
  1033     if (splash_file_name && !headlessflag) {
  1034         char* splash_file_entry = JLI_MemAlloc(strlen(SPLASH_FILE_ENV_ENTRY "=")+strlen(splash_file_name)+1);
  1035         strcpy(splash_file_entry, SPLASH_FILE_ENV_ENTRY "=");
  1036         strcat(splash_file_entry, splash_file_name);
  1037         putenv(splash_file_entry);
  1039     if (splash_jar_name && !headlessflag) {
  1040         char* splash_jar_entry = JLI_MemAlloc(strlen(SPLASH_JAR_ENV_ENTRY "=")+strlen(splash_jar_name)+1);
  1041         strcpy(splash_jar_entry, SPLASH_JAR_ENV_ENTRY "=");
  1042         strcat(splash_jar_entry, splash_jar_name);
  1043         putenv(splash_jar_entry);
  1046     /*
  1047      * The JRE-Version and JRE-Restrict-Search values (if any) from the
  1048      * manifest are overwritten by any specified on the command line.
  1049      */
  1050     if (version != NULL)
  1051         info.jre_version = version;
  1052     if (restrict_search != -1)
  1053         info.jre_restrict_search = restrict_search;
  1055     /*
  1056      * "Valid" returns (other than unrecoverable errors) follow.  Set
  1057      * main_class as a side-effect of this routine.
  1058      */
  1059     if (info.main_class != NULL)
  1060         *main_class = JLI_StringDup(info.main_class);
  1062     /*
  1063      * If no version selection information is found either on the command
  1064      * line or in the manifest, simply return.
  1065      */
  1066     if (info.jre_version == NULL) {
  1067         JLI_FreeManifest();
  1068         JLI_MemFree(new_argv);
  1069         return;
  1072     /*
  1073      * Check for correct syntax of the version specification (JSR 56).
  1074      */
  1075     if (!JLI_ValidVersionString(info.jre_version)) {
  1076         ReportErrorMessage2("Syntax error in version specification \"%s\"",
  1077           info.jre_version, JNI_TRUE);
  1078         exit(1);
  1081     /*
  1082      * Find the appropriate JVM on the system. Just to be as forgiving as
  1083      * possible, if the standard algorithms don't locate an appropriate
  1084      * jre, check to see if the one running will satisfy the requirements.
  1085      * This can happen on systems which haven't been set-up for multiple
  1086      * JRE support.
  1087      */
  1088     jre = LocateJRE(&info);
  1089     if (_launcher_debug)
  1090         printf("JRE-Version = %s, JRE-Restrict-Search = %s Selected = %s\n",
  1091           (info.jre_version?info.jre_version:"null"),
  1092           (info.jre_restrict_search?"true":"false"), (jre?jre:"null"));
  1093     if (jre == NULL) {
  1094         if (JLI_AcceptableRelease(FULL_VERSION, info.jre_version)) {
  1095             JLI_FreeManifest();
  1096             JLI_MemFree(new_argv);
  1097             return;
  1098         } else {
  1099             ReportErrorMessage2(
  1100               "Unable to locate JRE meeting specification \"%s\"",
  1101               info.jre_version, JNI_TRUE);
  1102             exit(1);
  1106     /*
  1107      * If I'm not the chosen one, exec the chosen one.  Returning from
  1108      * ExecJRE indicates that I am indeed the chosen one.
  1110      * The private environment variable _JAVA_VERSION_SET is used to
  1111      * prevent the chosen one from re-reading the manifest file and
  1112      * using the values found within to override the (potential) command
  1113      * line flags stripped from argv (because the target may not
  1114      * understand them).  Passing the MainClass value is an optimization
  1115      * to avoid locating, expanding and parsing the manifest extra
  1116      * times.
  1117      */
  1118     if (info.main_class != NULL) {
  1119         if (strlen(info.main_class) <= MAXNAMELEN) {
  1120             (void)strcat(env_entry, info.main_class);
  1121         } else {
  1122             ReportErrorMessage("Error: main-class: attribute exceeds system limits\n", JNI_TRUE);
  1123             exit(1);
  1126     (void)putenv(env_entry);
  1127     ExecJRE(jre, new_argv);
  1128     JLI_FreeManifest();
  1129     JLI_MemFree(new_argv);
  1130     return;
  1132 #endif /* ifndef GAMMA */
  1134 /*
  1135  * Parses command line arguments.  Returns JNI_FALSE if launcher
  1136  * should exit without starting vm (e.g. certain version and usage
  1137  * options); returns JNI_TRUE if vm needs to be started to process
  1138  * given options.  *pret (the launcher process return value) is set to
  1139  * 0 for a normal exit.
  1140  */
  1141 static jboolean
  1142 ParseArguments(int *pargc, char ***pargv, char **pjarfile,
  1143                        char **pclassname, int *pret, const char *jvmpath)
  1145     int argc = *pargc;
  1146     char **argv = *pargv;
  1147     jboolean jarflag = JNI_FALSE;
  1148     char *arg;
  1150     *pret = 1;
  1151     while ((arg = *argv) != 0 && *arg == '-') {
  1152         argv++; --argc;
  1153         if (strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) {
  1154             if (argc < 1) {
  1155                 ReportErrorMessage2("%s requires class path specification",
  1156                                     arg, JNI_TRUE);
  1157                 PrintUsage();
  1158                 return JNI_FALSE;
  1160             SetClassPath(*argv);
  1161             argv++; --argc;
  1162         } else if (strcmp(arg, "-jar") == 0) {
  1163             jarflag = JNI_TRUE;
  1164         } else if (strcmp(arg, "-help") == 0 ||
  1165                    strcmp(arg, "-h") == 0 ||
  1166                    strcmp(arg, "-?") == 0) {
  1167             PrintUsage();
  1168             *pret = 0;
  1169             return JNI_FALSE;
  1170         } else if (strcmp(arg, "-version") == 0) {
  1171             printVersion = JNI_TRUE;
  1172             return JNI_TRUE;
  1173         } else if (strcmp(arg, "-showversion") == 0) {
  1174             showVersion = JNI_TRUE;
  1175         } else if (strcmp(arg, "-X") == 0) {
  1176             *pret = PrintXUsage(jvmpath);
  1177             return JNI_FALSE;
  1178 /*
  1179  * The following case provide backward compatibility with old-style
  1180  * command line options.
  1181  */
  1182         } else if (strcmp(arg, "-fullversion") == 0) {
  1183             fprintf(stderr, "%s full version \"%s\"\n", progname,
  1184                     FULL_VERSION);
  1185             *pret = 0;
  1186             return JNI_FALSE;
  1187         } else if (strcmp(arg, "-verbosegc") == 0) {
  1188             AddOption("-verbose:gc", NULL);
  1189         } else if (strcmp(arg, "-t") == 0) {
  1190             AddOption("-Xt", NULL);
  1191         } else if (strcmp(arg, "-tm") == 0) {
  1192             AddOption("-Xtm", NULL);
  1193         } else if (strcmp(arg, "-debug") == 0) {
  1194             AddOption("-Xdebug", NULL);
  1195         } else if (strcmp(arg, "-noclassgc") == 0) {
  1196             AddOption("-Xnoclassgc", NULL);
  1197         } else if (strcmp(arg, "-Xfuture") == 0) {
  1198             AddOption("-Xverify:all", NULL);
  1199         } else if (strcmp(arg, "-verify") == 0) {
  1200             AddOption("-Xverify:all", NULL);
  1201         } else if (strcmp(arg, "-verifyremote") == 0) {
  1202             AddOption("-Xverify:remote", NULL);
  1203         } else if (strcmp(arg, "-noverify") == 0) {
  1204             AddOption("-Xverify:none", NULL);
  1205         } else if (strcmp(arg, "-XXsuppressExitMessage") == 0) {
  1206             noExitErrorMessage = 1;
  1207         } else if (strncmp(arg, "-prof", 5) == 0) {
  1208             char *p = arg + 5;
  1209             char *tmp = JLI_MemAlloc(strlen(arg) + 50);
  1210             if (*p) {
  1211                 sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1);
  1212             } else {
  1213                 sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof");
  1215             AddOption(tmp, NULL);
  1216         } else if (strncmp(arg, "-ss", 3) == 0 ||
  1217                    strncmp(arg, "-oss", 4) == 0 ||
  1218                    strncmp(arg, "-ms", 3) == 0 ||
  1219                    strncmp(arg, "-mx", 3) == 0) {
  1220             char *tmp = JLI_MemAlloc(strlen(arg) + 6);
  1221             sprintf(tmp, "-X%s", arg + 1); /* skip '-' */
  1222             AddOption(tmp, NULL);
  1223         } else if (strcmp(arg, "-checksource") == 0 ||
  1224                    strcmp(arg, "-cs") == 0 ||
  1225                    strcmp(arg, "-noasyncgc") == 0) {
  1226             /* No longer supported */
  1227             fprintf(stderr,
  1228                     "Warning: %s option is no longer supported.\n",
  1229                     arg);
  1230         } else if (strncmp(arg, "-version:", 9) == 0 ||
  1231                    strcmp(arg, "-no-jre-restrict-search") == 0 ||
  1232                    strcmp(arg, "-jre-restrict-search") == 0 ||
  1233                    strncmp(arg, "-splash:", 8) == 0) {
  1234             ; /* Ignore machine independent options already handled */
  1235         } else if (RemovableMachineDependentOption(arg) ) {
  1236             ; /* Do not pass option to vm. */
  1238         else {
  1239             AddOption(arg, NULL);
  1243     if (--argc >= 0) {
  1244         if (jarflag) {
  1245             *pjarfile = *argv++;
  1246             *pclassname = 0;
  1247         } else {
  1248             *pjarfile = 0;
  1249             *pclassname = *argv++;
  1251         *pargc = argc;
  1252         *pargv = argv;
  1255     return JNI_TRUE;
  1258 /*
  1259  * Initializes the Java Virtual Machine. Also frees options array when
  1260  * finished.
  1261  */
  1262 static jboolean
  1263 InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn)
  1265     JavaVMInitArgs args;
  1266     jint r;
  1268     memset(&args, 0, sizeof(args));
  1269     args.version  = JNI_VERSION_1_2;
  1270     args.nOptions = numOptions;
  1271     args.options  = options;
  1272     args.ignoreUnrecognized = JNI_FALSE;
  1274     if (_launcher_debug) {
  1275         int i = 0;
  1276         printf("JavaVM args:\n    ");
  1277         printf("version 0x%08lx, ", (long)args.version);
  1278         printf("ignoreUnrecognized is %s, ",
  1279                args.ignoreUnrecognized ? "JNI_TRUE" : "JNI_FALSE");
  1280         printf("nOptions is %ld\n", (long)args.nOptions);
  1281         for (i = 0; i < numOptions; i++)
  1282             printf("    option[%2d] = '%s'\n",
  1283                    i, args.options[i].optionString);
  1286     r = ifn->CreateJavaVM(pvm, (void **)penv, &args);
  1287     JLI_MemFree(options);
  1288     return r == JNI_OK;
  1292 #define NULL_CHECK0(e) if ((e) == 0) return 0
  1293 #define NULL_CHECK(e) if ((e) == 0) return
  1295 static jstring platformEncoding = NULL;
  1296 static jstring getPlatformEncoding(JNIEnv *env) {
  1297     if (platformEncoding == NULL) {
  1298         jstring propname = (*env)->NewStringUTF(env, "sun.jnu.encoding");
  1299         if (propname) {
  1300             jclass cls;
  1301             jmethodID mid;
  1302             NULL_CHECK0 (cls = (*env)->FindClass(env, "java/lang/System"));
  1303             NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
  1304                                    env, cls,
  1305                                    "getProperty",
  1306                                    "(Ljava/lang/String;)Ljava/lang/String;"));
  1307             platformEncoding = (*env)->CallStaticObjectMethod (
  1308                                     env, cls, mid, propname);
  1311     return platformEncoding;
  1314 static jboolean isEncodingSupported(JNIEnv *env, jstring enc) {
  1315     jclass cls;
  1316     jmethodID mid;
  1317     NULL_CHECK0 (cls = (*env)->FindClass(env, "java/nio/charset/Charset"));
  1318     NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
  1319                            env, cls,
  1320                            "isSupported",
  1321                            "(Ljava/lang/String;)Z"));
  1322     return (*env)->CallStaticBooleanMethod(env, cls, mid, enc);
  1325 /*
  1326  * Returns a new Java string object for the specified platform string.
  1327  */
  1328 static jstring
  1329 NewPlatformString(JNIEnv *env, char *s)
  1331     int len = (int)strlen(s);
  1332     jclass cls;
  1333     jmethodID mid;
  1334     jbyteArray ary;
  1335     jstring enc;
  1337     if (s == NULL)
  1338         return 0;
  1339     enc = getPlatformEncoding(env);
  1341     ary = (*env)->NewByteArray(env, len);
  1342     if (ary != 0) {
  1343         jstring str = 0;
  1344         (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s);
  1345         if (!(*env)->ExceptionOccurred(env)) {
  1346             if (isEncodingSupported(env, enc) == JNI_TRUE) {
  1347                 NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
  1348                 NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
  1349                                           "([BLjava/lang/String;)V"));
  1350                 str = (*env)->NewObject(env, cls, mid, ary, enc);
  1351             } else {
  1352                 /*If the encoding specified in sun.jnu.encoding is not
  1353                   endorsed by "Charset.isSupported" we have to fall back
  1354                   to use String(byte[]) explicitly here without specifying
  1355                   the encoding name, in which the StringCoding class will
  1356                   pickup the iso-8859-1 as the fallback converter for us.
  1357                 */
  1358                 NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
  1359                 NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
  1360                                           "([B)V"));
  1361                 str = (*env)->NewObject(env, cls, mid, ary);
  1363             (*env)->DeleteLocalRef(env, ary);
  1364             return str;
  1367     return 0;
  1370 /*
  1371  * Returns a new array of Java string objects for the specified
  1372  * array of platform strings.
  1373  */
  1374 static jobjectArray
  1375 NewPlatformStringArray(JNIEnv *env, char **strv, int strc)
  1377     jarray cls;
  1378     jarray ary;
  1379     int i;
  1381     NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
  1382     NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0));
  1383     for (i = 0; i < strc; i++) {
  1384         jstring str = NewPlatformString(env, *strv++);
  1385         NULL_CHECK0(str);
  1386         (*env)->SetObjectArrayElement(env, ary, i, str);
  1387         (*env)->DeleteLocalRef(env, str);
  1389     return ary;
  1392 /*
  1393  * Loads a class, convert the '.' to '/'.
  1394  */
  1395 static jclass
  1396 LoadClass(JNIEnv *env, char *name)
  1398     char *buf = JLI_MemAlloc(strlen(name) + 1);
  1399     char *s = buf, *t = name, c;
  1400     jclass cls;
  1401     jlong start, end;
  1403     if (_launcher_debug)
  1404         start = CounterGet();
  1406     do {
  1407         c = *t++;
  1408         *s++ = (c == '.') ? '/' : c;
  1409     } while (c != '\0');
  1410     cls = (*env)->FindClass(env, buf);
  1411     JLI_MemFree(buf);
  1413     if (_launcher_debug) {
  1414         end   = CounterGet();
  1415         printf("%ld micro seconds to load main class\n",
  1416                (long)(jint)Counter2Micros(end-start));
  1417         printf("----_JAVA_LAUNCHER_DEBUG----\n");
  1420     return cls;
  1424 /*
  1425  * Returns the main class name for the specified jar file.
  1426  */
  1427 static jstring
  1428 GetMainClassName(JNIEnv *env, char *jarname)
  1430 #define MAIN_CLASS "Main-Class"
  1431     jclass cls;
  1432     jmethodID mid;
  1433     jobject jar, man, attr;
  1434     jstring str, result = 0;
  1436     NULL_CHECK0(cls = (*env)->FindClass(env, "java/util/jar/JarFile"));
  1437     NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
  1438                                           "(Ljava/lang/String;)V"));
  1439     NULL_CHECK0(str = NewPlatformString(env, jarname));
  1440     NULL_CHECK0(jar = (*env)->NewObject(env, cls, mid, str));
  1441     NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "getManifest",
  1442                                           "()Ljava/util/jar/Manifest;"));
  1443     man = (*env)->CallObjectMethod(env, jar, mid);
  1444     if (man != 0) {
  1445         NULL_CHECK0(mid = (*env)->GetMethodID(env,
  1446                                     (*env)->GetObjectClass(env, man),
  1447                                     "getMainAttributes",
  1448                                     "()Ljava/util/jar/Attributes;"));
  1449         attr = (*env)->CallObjectMethod(env, man, mid);
  1450         if (attr != 0) {
  1451             NULL_CHECK0(mid = (*env)->GetMethodID(env,
  1452                                     (*env)->GetObjectClass(env, attr),
  1453                                     "getValue",
  1454                                     "(Ljava/lang/String;)Ljava/lang/String;"));
  1455             NULL_CHECK0(str = NewPlatformString(env, MAIN_CLASS));
  1456             result = (*env)->CallObjectMethod(env, attr, mid, str);
  1459     return result;
  1462 #ifdef JAVA_ARGS
  1463 static char *java_args[] = JAVA_ARGS;
  1464 static char *app_classpath[] = APP_CLASSPATH;
  1466 /*
  1467  * For tools, convert command line args thus:
  1468  *   javac -cp foo:foo/"*" -J-ms32m ...
  1469  *   java -ms32m -cp JLI_WildcardExpandClasspath(foo:foo/"*") ...
  1470  */
  1471 static void
  1472 TranslateApplicationArgs(int *pargc, char ***pargv)
  1474     const int NUM_ARGS = (sizeof(java_args) / sizeof(char *));
  1475     int argc = *pargc;
  1476     char **argv = *pargv;
  1477     int nargc = argc + NUM_ARGS;
  1478     char **nargv = JLI_MemAlloc((nargc + 1) * sizeof(char *));
  1479     int i;
  1481     *pargc = nargc;
  1482     *pargv = nargv;
  1484     /* Copy the VM arguments (i.e. prefixed with -J) */
  1485     for (i = 0; i < NUM_ARGS; i++) {
  1486         char *arg = java_args[i];
  1487         if (arg[0] == '-' && arg[1] == 'J') {
  1488             *nargv++ = arg + 2;
  1492     for (i = 0; i < argc; i++) {
  1493         char *arg = argv[i];
  1494         if (arg[0] == '-' && arg[1] == 'J') {
  1495             if (arg[2] == '\0') {
  1496                 ReportErrorMessage("Error: the -J option should not be "
  1497                                    "followed by a space.", JNI_TRUE);
  1498                 exit(1);
  1500             *nargv++ = arg + 2;
  1504     /* Copy the rest of the arguments */
  1505     for (i = 0; i < NUM_ARGS; i++) {
  1506         char *arg = java_args[i];
  1507         if (arg[0] != '-' || arg[1] != 'J') {
  1508             *nargv++ = arg;
  1511     for (i = 0; i < argc; i++) {
  1512         char *arg = argv[i];
  1513         if (arg[0] == '-') {
  1514             if (arg[1] == 'J')
  1515                 continue;
  1516 #ifdef EXPAND_CLASSPATH_WILDCARDS
  1517             if (arg[1] == 'c'
  1518                 && (strcmp(arg, "-cp") == 0 ||
  1519                     strcmp(arg, "-classpath") == 0)
  1520                 && i < argc - 1) {
  1521                 *nargv++ = arg;
  1522                 *nargv++ = (char *) JLI_WildcardExpandClasspath(argv[i+1]);
  1523                 i++;
  1524                 continue;
  1526 #endif
  1528         *nargv++ = arg;
  1530     *nargv = 0;
  1533 /*
  1534  * For our tools, we try to add 3 VM options:
  1535  *      -Denv.class.path=<envcp>
  1536  *      -Dapplication.home=<apphome>
  1537  *      -Djava.class.path=<appcp>
  1538  * <envcp>   is the user's setting of CLASSPATH -- for instance the user
  1539  *           tells javac where to find binary classes through this environment
  1540  *           variable.  Notice that users will be able to compile against our
  1541  *           tools classes (sun.tools.javac.Main) only if they explicitly add
  1542  *           tools.jar to CLASSPATH.
  1543  * <apphome> is the directory where the application is installed.
  1544  * <appcp>   is the classpath to where our apps' classfiles are.
  1545  */
  1546 static jboolean
  1547 AddApplicationOptions()
  1549     const int NUM_APP_CLASSPATH = (sizeof(app_classpath) / sizeof(char *));
  1550     char *envcp, *appcp, *apphome;
  1551     char home[MAXPATHLEN]; /* application home */
  1552     char separator[] = { PATH_SEPARATOR, '\0' };
  1553     int size, i;
  1554     int strlenHome;
  1557         const char *s = getenv("CLASSPATH");
  1558         if (s) {
  1559             s = (char *) JLI_WildcardExpandClasspath(s);
  1560             /* 40 for -Denv.class.path= */
  1561             envcp = (char *)JLI_MemAlloc(strlen(s) + 40);
  1562             sprintf(envcp, "-Denv.class.path=%s", s);
  1563             AddOption(envcp, NULL);
  1567     if (!GetApplicationHome(home, sizeof(home))) {
  1568         ReportErrorMessage("Can't determine application home", JNI_TRUE);
  1569         return JNI_FALSE;
  1572     /* 40 for '-Dapplication.home=' */
  1573     apphome = (char *)JLI_MemAlloc(strlen(home) + 40);
  1574     sprintf(apphome, "-Dapplication.home=%s", home);
  1575     AddOption(apphome, NULL);
  1577     /* How big is the application's classpath? */
  1578     size = 40;                                 /* 40: "-Djava.class.path=" */
  1579     strlenHome = (int)strlen(home);
  1580     for (i = 0; i < NUM_APP_CLASSPATH; i++) {
  1581         size += strlenHome + (int)strlen(app_classpath[i]) + 1; /* 1: separator */
  1583     appcp = (char *)JLI_MemAlloc(size + 1);
  1584     strcpy(appcp, "-Djava.class.path=");
  1585     for (i = 0; i < NUM_APP_CLASSPATH; i++) {
  1586         strcat(appcp, home);                    /* c:\program files\myapp */
  1587         strcat(appcp, app_classpath[i]);        /* \lib\myapp.jar         */
  1588         strcat(appcp, separator);               /* ;                      */
  1590     appcp[strlen(appcp)-1] = '\0';  /* remove trailing path separator */
  1591     AddOption(appcp, NULL);
  1592     return JNI_TRUE;
  1594 #endif /* JAVA_ARGS */
  1596 /*
  1597  * inject the -Dsun.java.command pseudo property into the args structure
  1598  * this pseudo property is used in the HotSpot VM to expose the
  1599  * Java class name and arguments to the main method to the VM. The
  1600  * HotSpot VM uses this pseudo property to store the Java class name
  1601  * (or jar file name) and the arguments to the class's main method
  1602  * to the instrumentation memory region. The sun.java.command pseudo
  1603  * property is not exported by HotSpot to the Java layer.
  1604  */
  1605 void
  1606 SetJavaCommandLineProp(char *classname, char *jarfile,
  1607                        int argc, char **argv)
  1610     int i = 0;
  1611     size_t len = 0;
  1612     char* javaCommand = NULL;
  1613     char* dashDstr = "-Dsun.java.command=";
  1615     if (classname == NULL && jarfile == NULL) {
  1616         /* unexpected, one of these should be set. just return without
  1617          * setting the property
  1618          */
  1619         return;
  1622     /* if the class name is not set, then use the jarfile name */
  1623     if (classname == NULL) {
  1624         classname = jarfile;
  1627     /* determine the amount of memory to allocate assuming
  1628      * the individual components will be space separated
  1629      */
  1630     len = strlen(classname);
  1631     for (i = 0; i < argc; i++) {
  1632         len += strlen(argv[i]) + 1;
  1635     /* allocate the memory */
  1636     javaCommand = (char*) JLI_MemAlloc(len + strlen(dashDstr) + 1);
  1638     /* build the -D string */
  1639     *javaCommand = '\0';
  1640     strcat(javaCommand, dashDstr);
  1641     strcat(javaCommand, classname);
  1643     for (i = 0; i < argc; i++) {
  1644         /* the components of the string are space separated. In
  1645          * the case of embedded white space, the relationship of
  1646          * the white space separated components to their true
  1647          * positional arguments will be ambiguous. This issue may
  1648          * be addressed in a future release.
  1649          */
  1650         strcat(javaCommand, " ");
  1651         strcat(javaCommand, argv[i]);
  1654     AddOption(javaCommand, NULL);
  1657 /*
  1658  * JVM would like to know if it's created by a standard Sun launcher, or by
  1659  * user native application, the following property indicates the former.
  1660  */
  1661 void SetJavaLauncherProp() {
  1662   AddOption("-Dsun.java.launcher=" LAUNCHER_TYPE, NULL);
  1665 /*
  1666  * Prints the version information from the java.version and other properties.
  1667  */
  1668 static void
  1669 PrintJavaVersion(JNIEnv *env)
  1671     jclass ver;
  1672     jmethodID print;
  1674     NULL_CHECK(ver = (*env)->FindClass(env, "sun/misc/Version"));
  1675     NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, "print", "()V"));
  1677     (*env)->CallStaticVoidMethod(env, ver, print);
  1680 /*
  1681  * Prints default usage message.
  1682  */
  1683 static void
  1684 PrintUsage(void)
  1686 #ifndef GAMMA
  1687     int i;
  1688 #endif
  1690     fprintf(stdout,
  1691         "Usage: %s [-options] class [args...]\n"
  1692         "           (to execute a class)\n"
  1693         "   or  %s [-options] -jar jarfile [args...]\n"
  1694         "           (to execute a jar file)\n"
  1695         "\n"
  1696         "where options include:\n",
  1697         progname,
  1698         progname);
  1700 #ifndef GAMMA
  1701     PrintMachineDependentOptions();
  1703     if ((knownVMs[0].flag == VM_KNOWN) ||
  1704         (knownVMs[0].flag == VM_IF_SERVER_CLASS)) {
  1705       fprintf(stdout, "    %s\t  to select the \"%s\" VM\n",
  1706               knownVMs[0].name, knownVMs[0].name+1);
  1708     for (i=1; i<knownVMsCount; i++) {
  1709         if (knownVMs[i].flag == VM_KNOWN)
  1710             fprintf(stdout, "    %s\t  to select the \"%s\" VM\n",
  1711                     knownVMs[i].name, knownVMs[i].name+1);
  1713     for (i=1; i<knownVMsCount; i++) {
  1714         if (knownVMs[i].flag == VM_ALIASED_TO)
  1715             fprintf(stdout, "    %s\t  is a synonym for "
  1716                     "the \"%s\" VM  [deprecated]\n",
  1717                     knownVMs[i].name, knownVMs[i].alias+1);
  1719     /* The first known VM is the default */
  1721       const char* defaultVM   = knownVMs[0].name+1;
  1722       const char* punctuation = ".";
  1723       const char* reason      = "";
  1724       if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) &&
  1725           (ServerClassMachine() == JNI_TRUE)) {
  1726         defaultVM = knownVMs[0].server_class+1;
  1727         punctuation = ", ";
  1728         reason = "because you are running on a server-class machine.\n";
  1730       fprintf(stdout, "                  The default VM is %s%s\n",
  1731               defaultVM, punctuation);
  1732       fprintf(stdout, "                  %s\n",
  1733               reason);
  1735 #endif /* ifndef GAMMA */
  1737     fprintf(stdout,
  1738 "    -cp <class search path of directories and zip/jar files>\n"
  1739 "    -classpath <class search path of directories and zip/jar files>\n"
  1740 "                  A %c separated list of directories, JAR archives,\n"
  1741 "                  and ZIP archives to search for class files.\n"
  1742 "    -D<name>=<value>\n"
  1743 "                  set a system property\n"
  1744 "    -verbose[:class|gc|jni]\n"
  1745 "                  enable verbose output\n"
  1746 "    -version      print product version and exit\n"
  1747 "    -version:<value>\n"
  1748 "                  require the specified version to run\n"
  1749 "    -showversion  print product version and continue\n"
  1750 "    -jre-restrict-search | -jre-no-restrict-search\n"
  1751 "                  include/exclude user private JREs in the version search\n"
  1752 "    -? -help      print this help message\n"
  1753 "    -X            print help on non-standard options\n"
  1754 "    -ea[:<packagename>...|:<classname>]\n"
  1755 "    -enableassertions[:<packagename>...|:<classname>]\n"
  1756 "                  enable assertions\n"
  1757 "    -da[:<packagename>...|:<classname>]\n"
  1758 "    -disableassertions[:<packagename>...|:<classname>]\n"
  1759 "                  disable assertions\n"
  1760 "    -esa | -enablesystemassertions\n"
  1761 "                  enable system assertions\n"
  1762 "    -dsa | -disablesystemassertions\n"
  1763 "                  disable system assertions\n"
  1764 "    -agentlib:<libname>[=<options>]\n"
  1765 "                  load native agent library <libname>, e.g. -agentlib:hprof\n"
  1766 "                    see also, -agentlib:jdwp=help and -agentlib:hprof=help\n"
  1767 "    -agentpath:<pathname>[=<options>]\n"
  1768 "                  load native agent library by full pathname\n"
  1769 "    -javaagent:<jarpath>[=<options>]\n"
  1770 "                  load Java programming language agent, see java.lang.instrument\n"
  1771 "    -splash:<imagepath>\n"
  1772 "                  show splash screen with specified image\n"
  1774             ,PATH_SEPARATOR);
  1777 /*
  1778  * Print usage message for -X options.
  1779  */
  1780 static jint
  1781 PrintXUsage(const char *jvmpath)
  1783     /*
  1784        A 32 bit cushion to prevent buffer overrun, noting that
  1785        fopen(3C) may fail if the buffer exceeds MAXPATHLEN.
  1786     */
  1787     char path[MAXPATHLEN+32];
  1788     char buf[128];
  1789     size_t n;
  1790     FILE *fp;
  1791     static const char Xusage_txt[] = "/Xusage.txt";
  1793     strcpy(path, jvmpath);
  1794     /* Note the FILE_SEPARATOR is platform dependent */
  1795     strcpy(strrchr(path, FILE_SEPARATOR), Xusage_txt);
  1796     fp = fopen(path, "r");
  1797     if (fp == 0) {
  1798         fprintf(stderr, "Can't open %s\n", path);
  1799         return 1;
  1801     while ((n = fread(buf, 1, sizeof(buf), fp)) != 0) {
  1802         fwrite(buf, 1, n, stdout);
  1804     fclose(fp);
  1805     return 0;
  1808 #ifndef GAMMA
  1809 /*
  1810  * Read the jvm.cfg file and fill the knownJVMs[] array.
  1812  * The functionality of the jvm.cfg file is subject to change without
  1813  * notice and the mechanism will be removed in the future.
  1815  * The lexical structure of the jvm.cfg file is as follows:
  1817  *     jvmcfg         :=  { vmLine }
  1818  *     vmLine         :=  knownLine
  1819  *                    |   aliasLine
  1820  *                    |   warnLine
  1821  *                    |   ignoreLine
  1822  *                    |   errorLine
  1823  *                    |   predicateLine
  1824  *                    |   commentLine
  1825  *     knownLine      :=  flag  "KNOWN"                  EOL
  1826  *     warnLine       :=  flag  "WARN"                   EOL
  1827  *     ignoreLine     :=  flag  "IGNORE"                 EOL
  1828  *     errorLine      :=  flag  "ERROR"                  EOL
  1829  *     aliasLine      :=  flag  "ALIASED_TO"       flag  EOL
  1830  *     predicateLine  :=  flag  "IF_SERVER_CLASS"  flag  EOL
  1831  *     commentLine    :=  "#" text                       EOL
  1832  *     flag           :=  "-" identifier
  1834  * The semantics are that when someone specifies a flag on the command line:
  1835  * - if the flag appears on a knownLine, then the identifier is used as
  1836  *   the name of the directory holding the JVM library (the name of the JVM).
  1837  * - if the flag appears as the first flag on an aliasLine, the identifier
  1838  *   of the second flag is used as the name of the JVM.
  1839  * - if the flag appears on a warnLine, the identifier is used as the
  1840  *   name of the JVM, but a warning is generated.
  1841  * - if the flag appears on an ignoreLine, the identifier is recognized as the
  1842  *   name of a JVM, but the identifier is ignored and the default vm used
  1843  * - if the flag appears on an errorLine, an error is generated.
  1844  * - if the flag appears as the first flag on a predicateLine, and
  1845  *   the machine on which you are running passes the predicate indicated,
  1846  *   then the identifier of the second flag is used as the name of the JVM,
  1847  *   otherwise the identifier of the first flag is used as the name of the JVM.
  1848  * If no flag is given on the command line, the first vmLine of the jvm.cfg
  1849  * file determines the name of the JVM.
  1850  * PredicateLines are only interpreted on first vmLine of a jvm.cfg file,
  1851  * since they only make sense if someone hasn't specified the name of the
  1852  * JVM on the command line.
  1854  * The intent of the jvm.cfg file is to allow several JVM libraries to
  1855  * be installed in different subdirectories of a single JRE installation,
  1856  * for space-savings and convenience in testing.
  1857  * The intent is explicitly not to provide a full aliasing or predicate
  1858  * mechanism.
  1859  */
  1860 jint
  1861 ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative)
  1863     FILE *jvmCfg;
  1864     char jvmCfgName[MAXPATHLEN+20];
  1865     char line[MAXPATHLEN+20];
  1866     int cnt = 0;
  1867     int lineno = 0;
  1868     jlong start, end;
  1869     int vmType;
  1870     char *tmpPtr;
  1871     char *altVMName = NULL;
  1872     char *serverClassVMName = NULL;
  1873     static char *whiteSpace = " \t";
  1874     if (_launcher_debug) {
  1875         start = CounterGet();
  1878     strcpy(jvmCfgName, jrepath);
  1879     strcat(jvmCfgName, FILESEP "lib" FILESEP);
  1880     strcat(jvmCfgName, arch);
  1881     strcat(jvmCfgName, FILESEP "jvm.cfg");
  1883     jvmCfg = fopen(jvmCfgName, "r");
  1884     if (jvmCfg == NULL) {
  1885       if (!speculative) {
  1886         ReportErrorMessage2("Error: could not open `%s'", jvmCfgName,
  1887                             JNI_TRUE);
  1888         exit(1);
  1889       } else {
  1890         return -1;
  1893     while (fgets(line, sizeof(line), jvmCfg) != NULL) {
  1894         vmType = VM_UNKNOWN;
  1895         lineno++;
  1896         if (line[0] == '#')
  1897             continue;
  1898         if (line[0] != '-') {
  1899             fprintf(stderr, "Warning: no leading - on line %d of `%s'\n",
  1900                     lineno, jvmCfgName);
  1902         if (cnt >= knownVMsLimit) {
  1903             GrowKnownVMs(cnt);
  1905         line[strlen(line)-1] = '\0'; /* remove trailing newline */
  1906         tmpPtr = line + strcspn(line, whiteSpace);
  1907         if (*tmpPtr == 0) {
  1908             fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n",
  1909                     lineno, jvmCfgName);
  1910         } else {
  1911             /* Null-terminate this string for JLI_StringDup below */
  1912             *tmpPtr++ = 0;
  1913             tmpPtr += strspn(tmpPtr, whiteSpace);
  1914             if (*tmpPtr == 0) {
  1915                 fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n",
  1916                         lineno, jvmCfgName);
  1917             } else {
  1918                 if (!strncmp(tmpPtr, "KNOWN", strlen("KNOWN"))) {
  1919                     vmType = VM_KNOWN;
  1920                 } else if (!strncmp(tmpPtr, "ALIASED_TO", strlen("ALIASED_TO"))) {
  1921                     tmpPtr += strcspn(tmpPtr, whiteSpace);
  1922                     if (*tmpPtr != 0) {
  1923                         tmpPtr += strspn(tmpPtr, whiteSpace);
  1925                     if (*tmpPtr == 0) {
  1926                         fprintf(stderr, "Warning: missing VM alias on line %d of `%s'\n",
  1927                                 lineno, jvmCfgName);
  1928                     } else {
  1929                         /* Null terminate altVMName */
  1930                         altVMName = tmpPtr;
  1931                         tmpPtr += strcspn(tmpPtr, whiteSpace);
  1932                         *tmpPtr = 0;
  1933                         vmType = VM_ALIASED_TO;
  1935                 } else if (!strncmp(tmpPtr, "WARN", strlen("WARN"))) {
  1936                     vmType = VM_WARN;
  1937                 } else if (!strncmp(tmpPtr, "IGNORE", strlen("IGNORE"))) {
  1938                     vmType = VM_IGNORE;
  1939                 } else if (!strncmp(tmpPtr, "ERROR", strlen("ERROR"))) {
  1940                     vmType = VM_ERROR;
  1941                 } else if (!strncmp(tmpPtr,
  1942                                     "IF_SERVER_CLASS",
  1943                                     strlen("IF_SERVER_CLASS"))) {
  1944                     tmpPtr += strcspn(tmpPtr, whiteSpace);
  1945                     if (*tmpPtr != 0) {
  1946                         tmpPtr += strspn(tmpPtr, whiteSpace);
  1948                     if (*tmpPtr == 0) {
  1949                         fprintf(stderr, "Warning: missing server class VM on line %d of `%s'\n",
  1950                                 lineno, jvmCfgName);
  1951                     } else {
  1952                         /* Null terminate server class VM name */
  1953                         serverClassVMName = tmpPtr;
  1954                         tmpPtr += strcspn(tmpPtr, whiteSpace);
  1955                         *tmpPtr = 0;
  1956                         vmType = VM_IF_SERVER_CLASS;
  1958                 } else {
  1959                     fprintf(stderr, "Warning: unknown VM type on line %d of `%s'\n",
  1960                             lineno, &jvmCfgName[0]);
  1961                     vmType = VM_KNOWN;
  1966         if (_launcher_debug)
  1967             printf("jvm.cfg[%d] = ->%s<-\n", cnt, line);
  1968         if (vmType != VM_UNKNOWN) {
  1969             knownVMs[cnt].name = JLI_StringDup(line);
  1970             knownVMs[cnt].flag = vmType;
  1971             switch (vmType) {
  1972             default:
  1973                 break;
  1974             case VM_ALIASED_TO:
  1975                 knownVMs[cnt].alias = JLI_StringDup(altVMName);
  1976                 if (_launcher_debug) {
  1977                     printf("    name: %s  vmType: %s  alias: %s\n",
  1978                            knownVMs[cnt].name, "VM_ALIASED_TO", knownVMs[cnt].alias);
  1980                 break;
  1981             case VM_IF_SERVER_CLASS:
  1982                 knownVMs[cnt].server_class = JLI_StringDup(serverClassVMName);
  1983                 if (_launcher_debug) {
  1984                     printf("    name: %s  vmType: %s  server_class: %s\n",
  1985                            knownVMs[cnt].name, "VM_IF_SERVER_CLASS", knownVMs[cnt].server_class);
  1987                 break;
  1989             cnt++;
  1992     fclose(jvmCfg);
  1993     knownVMsCount = cnt;
  1995     if (_launcher_debug) {
  1996         end   = CounterGet();
  1997         printf("%ld micro seconds to parse jvm.cfg\n",
  1998                (long)(jint)Counter2Micros(end-start));
  2001     return cnt;
  2005 static void
  2006 GrowKnownVMs(int minimum)
  2008     struct vmdesc* newKnownVMs;
  2009     int newMax;
  2011     newMax = (knownVMsLimit == 0 ? INIT_MAX_KNOWN_VMS : (2 * knownVMsLimit));
  2012     if (newMax <= minimum) {
  2013         newMax = minimum;
  2015     newKnownVMs = (struct vmdesc*) JLI_MemAlloc(newMax * sizeof(struct vmdesc));
  2016     if (knownVMs != NULL) {
  2017         memcpy(newKnownVMs, knownVMs, knownVMsLimit * sizeof(struct vmdesc));
  2019     JLI_MemFree(knownVMs);
  2020     knownVMs = newKnownVMs;
  2021     knownVMsLimit = newMax;
  2025 /* Returns index of VM or -1 if not found */
  2026 static int
  2027 KnownVMIndex(const char* name)
  2029     int i;
  2030     if (strncmp(name, "-J", 2) == 0) name += 2;
  2031     for (i = 0; i < knownVMsCount; i++) {
  2032         if (!strcmp(name, knownVMs[i].name)) {
  2033             return i;
  2036     return -1;
  2039 static void
  2040 FreeKnownVMs()
  2042     int i;
  2043     for (i = 0; i < knownVMsCount; i++) {
  2044         JLI_MemFree(knownVMs[i].name);
  2045         knownVMs[i].name = NULL;
  2047     JLI_MemFree(knownVMs);
  2051 /*
  2052  * Displays the splash screen according to the jar file name
  2053  * and image file names stored in environment variables
  2054  */
  2055 static void
  2056 ShowSplashScreen()
  2058     const char *jar_name = getenv(SPLASH_JAR_ENV_ENTRY);
  2059     const char *file_name = getenv(SPLASH_FILE_ENV_ENTRY);
  2060     int data_size;
  2061     void *image_data;
  2062     if (jar_name) {
  2063         image_data = JLI_JarUnpackFile(jar_name, file_name, &data_size);
  2064         if (image_data) {
  2065             DoSplashInit();
  2066             DoSplashLoadMemory(image_data, data_size);
  2067             JLI_MemFree(image_data);
  2069     } else if (file_name) {
  2070         DoSplashInit();
  2071         DoSplashLoadFile(file_name);
  2072     } else {
  2073         return;
  2075     DoSplashSetFileJarName(file_name, jar_name);
  2078 #endif /* ifndef GAMMA */

mercurial