1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/os/solaris/launcher/java.c Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,1841 @@ 1.4 +/* 1.5 + * Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +/* 1.29 + * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK, 1.30 + * search "GAMMA" for gamma specific changes. 1.31 + * 1.32 + * GAMMA: gamma launcher is much simpler than regular java launcher in that 1.33 + * JVM is either statically linked in or it is installed in the 1.34 + * same directory where the launcher exists, so we don't have to 1.35 + * worry about choosing the right JVM based on command line flag, jar 1.36 + * file and/or ergonomics. Intead of removing unused logic from source 1.37 + * they are commented out with #ifndef GAMMA, hopefully it'll be easier 1.38 + * to maintain this file in sync with regular JDK launcher. 1.39 + */ 1.40 + 1.41 +/* 1.42 + * Shared source for 'java' command line tool. 1.43 + * 1.44 + * If JAVA_ARGS is defined, then acts as a launcher for applications. For 1.45 + * instance, the JDK command line tools such as javac and javadoc (see 1.46 + * makefiles for more details) are built with this program. Any arguments 1.47 + * prefixed with '-J' will be passed directly to the 'java' command. 1.48 + */ 1.49 + 1.50 +#ifdef GAMMA 1.51 +# ifdef JAVA_ARGS 1.52 +# error Do NOT define JAVA_ARGS when building gamma launcher 1.53 +# endif 1.54 +# if !defined(LINK_INTO_AOUT) && !defined(LINK_INTO_LIBJVM) 1.55 +# error Either LINK_INTO_AOUT or LINK_INTO_LIBJVM must be defined 1.56 +# endif 1.57 +#endif 1.58 + 1.59 +/* 1.60 + * One job of the launcher is to remove command line options which the 1.61 + * vm does not understand and will not process. These options include 1.62 + * options which select which style of vm is run (e.g. -client and 1.63 + * -server) as well as options which select the data model to use. 1.64 + * Additionally, for tools which invoke an underlying vm "-J-foo" 1.65 + * options are turned into "-foo" options to the vm. This option 1.66 + * filtering is handled in a number of places in the launcher, some of 1.67 + * it in machine-dependent code. In this file, the function 1.68 + * CheckJVMType removes vm style options and TranslateDashJArgs 1.69 + * removes "-J" prefixes. On unix platforms, the 1.70 + * CreateExecutionEnvironment function from the unix java_md.c file 1.71 + * processes and removes -d<n> options. However, in case 1.72 + * CreateExecutionEnvironment does not need to exec because 1.73 + * LD_LIBRARY_PATH is set acceptably and the data model does not need 1.74 + * to be changed, ParseArguments will screen out the redundant -d<n> 1.75 + * options and prevent them from being passed to the vm; this is done 1.76 + * by using the machine-dependent call 1.77 + * RemovableMachineDependentOption. 1.78 + */ 1.79 + 1.80 +#include <stdio.h> 1.81 +#include <stdlib.h> 1.82 +#include <string.h> 1.83 + 1.84 +#include <jni.h> 1.85 +#include "java.h" 1.86 + 1.87 +#ifndef GAMMA 1.88 +#include "manifest_info.h" 1.89 +#include "version_comp.h" 1.90 +#endif 1.91 + 1.92 +#ifndef FULL_VERSION 1.93 +#define FULL_VERSION JDK_MAJOR_VERSION "." JDK_MINOR_VERSION 1.94 +#endif 1.95 + 1.96 +/* 1.97 + * The following environment variable is used to influence the behavior 1.98 + * of the jre exec'd through the SelectVersion routine. The command line 1.99 + * options which specify the version are not passed to the exec'd version, 1.100 + * because that jre may be an older version which wouldn't recognize them. 1.101 + * This environment variable is known to this (and later) version and serves 1.102 + * to suppress the version selection code. This is not only for efficiency, 1.103 + * but also for correctness, since any command line options have been 1.104 + * removed which would cause any value found in the manifest to be used. 1.105 + * This would be incorrect because the command line options are defined 1.106 + * to take precedence. 1.107 + * 1.108 + * The value associated with this environment variable is the MainClass 1.109 + * name from within the executable jar file (if any). This is strictly a 1.110 + * performance enhancement to avoid re-reading the jar file manifest. 1.111 + * 1.112 + * A NOTE TO DEVELOPERS: For performance reasons it is important that 1.113 + * the program image remain relatively small until after SelectVersion 1.114 + * CreateExecutionEnvironment have finished their possibly recursive 1.115 + * processing. Watch everything, but resist all temptations to use Java 1.116 + * interfaces. 1.117 + */ 1.118 +#define ENV_ENTRY "_JAVA_VERSION_SET" 1.119 + 1.120 +static jboolean printVersion = JNI_FALSE; /* print and exit */ 1.121 +static jboolean showVersion = JNI_FALSE; /* print but continue */ 1.122 +static char *progname; 1.123 +jboolean _launcher_debug = JNI_FALSE; 1.124 + 1.125 +/* 1.126 + * List of VM options to be specified when the VM is created. 1.127 + */ 1.128 +static JavaVMOption *options; 1.129 +static int numOptions, maxOptions; 1.130 + 1.131 +/* 1.132 + * Prototypes for functions internal to launcher. 1.133 + */ 1.134 +static void AddOption(char *str, void *info); 1.135 +static void SetClassPath(char *s); 1.136 +static void SelectVersion(int argc, char **argv, char **main_class); 1.137 +static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile, 1.138 + char **pclassname, int *pret); 1.139 +static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv, 1.140 + InvocationFunctions *ifn); 1.141 +static jstring NewPlatformString(JNIEnv *env, char *s); 1.142 +static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc); 1.143 +static jclass LoadClass(JNIEnv *env, char *name); 1.144 +static jstring GetMainClassName(JNIEnv *env, char *jarname); 1.145 +static void SetJavaCommandLineProp(char* classname, char* jarfile, int argc, char** argv); 1.146 +#ifdef GAMMA 1.147 +static void SetJavaLauncherProp(void); 1.148 +#endif 1.149 + 1.150 +#ifdef JAVA_ARGS 1.151 +static void TranslateDashJArgs(int *pargc, char ***pargv); 1.152 +static jboolean AddApplicationOptions(void); 1.153 +#endif 1.154 + 1.155 +static void PrintJavaVersion(JNIEnv *env); 1.156 +static void PrintUsage(void); 1.157 +static jint PrintXUsage(void); 1.158 + 1.159 +static void SetPaths(int argc, char **argv); 1.160 + 1.161 +/* Maximum supported entries from jvm.cfg. */ 1.162 +#define INIT_MAX_KNOWN_VMS 10 1.163 +/* Values for vmdesc.flag */ 1.164 +#define VM_UNKNOWN -1 1.165 +#define VM_KNOWN 0 1.166 +#define VM_ALIASED_TO 1 1.167 +#define VM_WARN 2 1.168 +#define VM_ERROR 3 1.169 +#define VM_IF_SERVER_CLASS 4 1.170 +#define VM_IGNORE 5 1.171 +struct vmdesc { 1.172 + char *name; 1.173 + int flag; 1.174 + char *alias; 1.175 + char *server_class; 1.176 +}; 1.177 +static struct vmdesc *knownVMs = NULL; 1.178 +static int knownVMsCount = 0; 1.179 +static int knownVMsLimit = 0; 1.180 + 1.181 +static void GrowKnownVMs(); 1.182 +static int KnownVMIndex(const char* name); 1.183 +static void FreeKnownVMs(); 1.184 + 1.185 +jboolean ServerClassMachine(); 1.186 + 1.187 +/* flag which if set suppresses error messages from the launcher */ 1.188 +static int noExitErrorMessage = 0; 1.189 + 1.190 +/* 1.191 + * Entry point. 1.192 + */ 1.193 +int 1.194 +main(int argc, char ** argv) 1.195 +{ 1.196 + JavaVM *vm = 0; 1.197 + JNIEnv *env = 0; 1.198 + char *jarfile = 0; 1.199 + char *classname = 0; 1.200 + char *s = 0; 1.201 + char *main_class = NULL; 1.202 + jstring mainClassName; 1.203 + jclass mainClass; 1.204 + jmethodID mainID; 1.205 + jobjectArray mainArgs; 1.206 + int ret; 1.207 + InvocationFunctions ifn; 1.208 + jlong start, end; 1.209 + char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN]; 1.210 + char ** original_argv = argv; 1.211 + 1.212 + /* 1.213 + * Error message to print or display; by default the message will 1.214 + * only be displayed in a window. 1.215 + */ 1.216 + char * message = "Fatal exception occurred. Program will exit."; 1.217 + jboolean messageDest = JNI_FALSE; 1.218 + 1.219 + if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) { 1.220 + _launcher_debug = JNI_TRUE; 1.221 + printf("----_JAVA_LAUNCHER_DEBUG----\n"); 1.222 + } 1.223 + 1.224 +#ifndef GAMMA 1.225 + /* 1.226 + * Make sure the specified version of the JRE is running. 1.227 + * 1.228 + * There are three things to note about the SelectVersion() routine: 1.229 + * 1) If the version running isn't correct, this routine doesn't 1.230 + * return (either the correct version has been exec'd or an error 1.231 + * was issued). 1.232 + * 2) Argc and Argv in this scope are *not* altered by this routine. 1.233 + * It is the responsibility of subsequent code to ignore the 1.234 + * arguments handled by this routine. 1.235 + * 3) As a side-effect, the variable "main_class" is guaranteed to 1.236 + * be set (if it should ever be set). This isn't exactly the 1.237 + * poster child for structured programming, but it is a small 1.238 + * price to pay for not processing a jar file operand twice. 1.239 + * (Note: This side effect has been disabled. See comment on 1.240 + * bugid 5030265 below.) 1.241 + */ 1.242 + SelectVersion(argc, argv, &main_class); 1.243 +#endif /* ifndef GAMMA */ 1.244 + 1.245 + /* copy original argv */ 1.246 + { 1.247 + int i; 1.248 + original_argv = (char**)MemAlloc(sizeof(char*)*(argc+1)); 1.249 + for(i = 0; i < argc+1; i++) 1.250 + original_argv[i] = argv[i]; 1.251 + } 1.252 + 1.253 + CreateExecutionEnvironment(&argc, &argv, 1.254 + jrepath, sizeof(jrepath), 1.255 + jvmpath, sizeof(jvmpath), 1.256 + original_argv); 1.257 + ifn.CreateJavaVM = 0; 1.258 + ifn.GetDefaultJavaVMInitArgs = 0; 1.259 + 1.260 + if (_launcher_debug) 1.261 + start = CounterGet(); 1.262 + if (!LoadJavaVM(jvmpath, &ifn)) { 1.263 + exit(6); 1.264 + } 1.265 + if (_launcher_debug) { 1.266 + end = CounterGet(); 1.267 + printf("%ld micro seconds to LoadJavaVM\n", 1.268 + (long)(jint)Counter2Micros(end-start)); 1.269 + } 1.270 + 1.271 +#ifdef JAVA_ARGS /* javac, jar and friends. */ 1.272 + progname = "java"; 1.273 +#else /* java, oldjava, javaw and friends */ 1.274 +#ifdef PROGNAME 1.275 + progname = PROGNAME; 1.276 +#else 1.277 + progname = *argv; 1.278 + if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) { 1.279 + progname = s + 1; 1.280 + } 1.281 +#endif /* PROGNAME */ 1.282 +#endif /* JAVA_ARGS */ 1.283 + ++argv; 1.284 + --argc; 1.285 + 1.286 +#ifdef JAVA_ARGS 1.287 + /* Preprocess wrapper arguments */ 1.288 + TranslateDashJArgs(&argc, &argv); 1.289 + if (!AddApplicationOptions()) { 1.290 + exit(1); 1.291 + } 1.292 +#endif 1.293 + 1.294 + /* Set default CLASSPATH */ 1.295 + if ((s = getenv("CLASSPATH")) == 0) { 1.296 + s = "."; 1.297 + } 1.298 +#ifndef JAVA_ARGS 1.299 + SetClassPath(s); 1.300 +#endif 1.301 + 1.302 + /* 1.303 + * Parse command line options; if the return value of 1.304 + * ParseArguments is false, the program should exit. 1.305 + */ 1.306 + if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret)) { 1.307 + exit(ret); 1.308 + } 1.309 + 1.310 + /* Override class path if -jar flag was specified */ 1.311 + if (jarfile != 0) { 1.312 + SetClassPath(jarfile); 1.313 + } 1.314 + 1.315 + /* set the -Dsun.java.command pseudo property */ 1.316 + SetJavaCommandLineProp(classname, jarfile, argc, argv); 1.317 + 1.318 +#ifdef GAMMA 1.319 + /* Set the -Dsun.java.launcher pseudo property */ 1.320 + SetJavaLauncherProp(); 1.321 +#endif 1.322 + 1.323 + /* 1.324 + * Done with all command line processing and potential re-execs so 1.325 + * clean up the environment. 1.326 + */ 1.327 + (void)UnsetEnv(ENV_ENTRY); 1.328 + 1.329 + /* Initialize the virtual machine */ 1.330 + 1.331 + if (_launcher_debug) 1.332 + start = CounterGet(); 1.333 + if (!InitializeJVM(&vm, &env, &ifn)) { 1.334 + ReportErrorMessage("Could not create the Java virtual machine.", 1.335 + JNI_TRUE); 1.336 + exit(1); 1.337 + } 1.338 + 1.339 + if (printVersion || showVersion) { 1.340 + PrintJavaVersion(env); 1.341 + if ((*env)->ExceptionOccurred(env)) { 1.342 + ReportExceptionDescription(env); 1.343 + goto leave; 1.344 + } 1.345 + if (printVersion) { 1.346 + ret = 0; 1.347 + message = NULL; 1.348 + goto leave; 1.349 + } 1.350 + if (showVersion) { 1.351 + fprintf(stderr, "\n"); 1.352 + } 1.353 + } 1.354 + 1.355 + /* If the user specified neither a class name nor a JAR file */ 1.356 + if (jarfile == 0 && classname == 0) { 1.357 + PrintUsage(); 1.358 + message = NULL; 1.359 + goto leave; 1.360 + } 1.361 + 1.362 +#ifndef GAMMA 1.363 + FreeKnownVMs(); /* after last possible PrintUsage() */ 1.364 +#endif 1.365 + 1.366 + if (_launcher_debug) { 1.367 + end = CounterGet(); 1.368 + printf("%ld micro seconds to InitializeJVM\n", 1.369 + (long)(jint)Counter2Micros(end-start)); 1.370 + } 1.371 + 1.372 + /* At this stage, argc/argv have the applications' arguments */ 1.373 + if (_launcher_debug) { 1.374 + int i = 0; 1.375 + printf("Main-Class is '%s'\n", classname ? classname : ""); 1.376 + printf("Apps' argc is %d\n", argc); 1.377 + for (; i < argc; i++) { 1.378 + printf(" argv[%2d] = '%s'\n", i, argv[i]); 1.379 + } 1.380 + } 1.381 + 1.382 + ret = 1; 1.383 + 1.384 + /* 1.385 + * Get the application's main class. 1.386 + * 1.387 + * See bugid 5030265. The Main-Class name has already been parsed 1.388 + * from the manifest, but not parsed properly for UTF-8 support. 1.389 + * Hence the code here ignores the value previously extracted and 1.390 + * uses the pre-existing code to reextract the value. This is 1.391 + * possibly an end of release cycle expedient. However, it has 1.392 + * also been discovered that passing some character sets through 1.393 + * the environment has "strange" behavior on some variants of 1.394 + * Windows. Hence, maybe the manifest parsing code local to the 1.395 + * launcher should never be enhanced. 1.396 + * 1.397 + * Hence, future work should either: 1.398 + * 1) Correct the local parsing code and verify that the 1.399 + * Main-Class attribute gets properly passed through 1.400 + * all environments, 1.401 + * 2) Remove the vestages of maintaining main_class through 1.402 + * the environment (and remove these comments). 1.403 + */ 1.404 + if (jarfile != 0) { 1.405 + mainClassName = GetMainClassName(env, jarfile); 1.406 + if ((*env)->ExceptionOccurred(env)) { 1.407 + ReportExceptionDescription(env); 1.408 + goto leave; 1.409 + } 1.410 + if (mainClassName == NULL) { 1.411 + const char * format = "Failed to load Main-Class manifest " 1.412 + "attribute from\n%s"; 1.413 + message = (char*)MemAlloc((strlen(format) + strlen(jarfile)) * 1.414 + sizeof(char)); 1.415 + sprintf(message, format, jarfile); 1.416 + messageDest = JNI_TRUE; 1.417 + goto leave; 1.418 + } 1.419 + classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0); 1.420 + if (classname == NULL) { 1.421 + ReportExceptionDescription(env); 1.422 + goto leave; 1.423 + } 1.424 + mainClass = LoadClass(env, classname); 1.425 + if(mainClass == NULL) { /* exception occured */ 1.426 + ReportExceptionDescription(env); 1.427 + message = "Could not find the main class. Program will exit."; 1.428 + goto leave; 1.429 + } 1.430 + (*env)->ReleaseStringUTFChars(env, mainClassName, classname); 1.431 + } else { 1.432 + mainClassName = NewPlatformString(env, classname); 1.433 + if (mainClassName == NULL) { 1.434 + const char * format = "Failed to load Main Class: %s"; 1.435 + message = (char *)MemAlloc((strlen(format) + strlen(classname)) * 1.436 + sizeof(char) ); 1.437 + sprintf(message, format, classname); 1.438 + messageDest = JNI_TRUE; 1.439 + goto leave; 1.440 + } 1.441 + classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0); 1.442 + if (classname == NULL) { 1.443 + ReportExceptionDescription(env); 1.444 + goto leave; 1.445 + } 1.446 + mainClass = LoadClass(env, classname); 1.447 + if(mainClass == NULL) { /* exception occured */ 1.448 + ReportExceptionDescription(env); 1.449 + message = "Could not find the main class. Program will exit."; 1.450 + goto leave; 1.451 + } 1.452 + (*env)->ReleaseStringUTFChars(env, mainClassName, classname); 1.453 + } 1.454 + 1.455 + /* Get the application's main method */ 1.456 + mainID = (*env)->GetStaticMethodID(env, mainClass, "main", 1.457 + "([Ljava/lang/String;)V"); 1.458 + if (mainID == NULL) { 1.459 + if ((*env)->ExceptionOccurred(env)) { 1.460 + ReportExceptionDescription(env); 1.461 + } else { 1.462 + message = "No main method found in specified class."; 1.463 + messageDest = JNI_TRUE; 1.464 + } 1.465 + goto leave; 1.466 + } 1.467 + 1.468 + { /* Make sure the main method is public */ 1.469 + jint mods; 1.470 + jmethodID mid; 1.471 + jobject obj = (*env)->ToReflectedMethod(env, mainClass, 1.472 + mainID, JNI_TRUE); 1.473 + 1.474 + if( obj == NULL) { /* exception occurred */ 1.475 + ReportExceptionDescription(env); 1.476 + goto leave; 1.477 + } 1.478 + 1.479 + mid = 1.480 + (*env)->GetMethodID(env, 1.481 + (*env)->GetObjectClass(env, obj), 1.482 + "getModifiers", "()I"); 1.483 + if ((*env)->ExceptionOccurred(env)) { 1.484 + ReportExceptionDescription(env); 1.485 + goto leave; 1.486 + } 1.487 + 1.488 + mods = (*env)->CallIntMethod(env, obj, mid); 1.489 + if ((mods & 1) == 0) { /* if (!Modifier.isPublic(mods)) ... */ 1.490 + message = "Main method not public."; 1.491 + messageDest = JNI_TRUE; 1.492 + goto leave; 1.493 + } 1.494 + } 1.495 + 1.496 + /* Build argument array */ 1.497 + mainArgs = NewPlatformStringArray(env, argv, argc); 1.498 + if (mainArgs == NULL) { 1.499 + ReportExceptionDescription(env); 1.500 + goto leave; 1.501 + } 1.502 + 1.503 + /* Invoke main method. */ 1.504 + (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); 1.505 + 1.506 + /* 1.507 + * The launcher's exit code (in the absence of calls to 1.508 + * System.exit) will be non-zero if main threw an exception. 1.509 + */ 1.510 + ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1; 1.511 + 1.512 + /* 1.513 + * Detach the main thread so that it appears to have ended when 1.514 + * the application's main method exits. This will invoke the 1.515 + * uncaught exception handler machinery if main threw an 1.516 + * exception. An uncaught exception handler cannot change the 1.517 + * launcher's return code except by calling System.exit. 1.518 + */ 1.519 + if ((*vm)->DetachCurrentThread(vm) != 0) { 1.520 + message = "Could not detach main thread."; 1.521 + messageDest = JNI_TRUE; 1.522 + ret = 1; 1.523 + goto leave; 1.524 + } 1.525 + 1.526 + message = NULL; 1.527 + 1.528 + leave: 1.529 + /* 1.530 + * Wait for all non-daemon threads to end, then destroy the VM. 1.531 + * This will actually create a trivial new Java waiter thread 1.532 + * named "DestroyJavaVM", but this will be seen as a different 1.533 + * thread from the one that executed main, even though they are 1.534 + * the same C thread. This allows mainThread.join() and 1.535 + * mainThread.isAlive() to work as expected. 1.536 + */ 1.537 + (*vm)->DestroyJavaVM(vm); 1.538 + 1.539 + if(message != NULL && !noExitErrorMessage) 1.540 + ReportErrorMessage(message, messageDest); 1.541 + return ret; 1.542 +} 1.543 + 1.544 + 1.545 +#ifndef GAMMA 1.546 +/* 1.547 + * Checks the command line options to find which JVM type was 1.548 + * specified. If no command line option was given for the JVM type, 1.549 + * the default type is used. The environment variable 1.550 + * JDK_ALTERNATE_VM and the command line option -XXaltjvm= are also 1.551 + * checked as ways of specifying which JVM type to invoke. 1.552 + */ 1.553 +char * 1.554 +CheckJvmType(int *pargc, char ***argv, jboolean speculative) { 1.555 + int i, argi; 1.556 + int argc; 1.557 + char **newArgv; 1.558 + int newArgvIdx = 0; 1.559 + int isVMType; 1.560 + int jvmidx = -1; 1.561 + char *jvmtype = getenv("JDK_ALTERNATE_VM"); 1.562 + 1.563 + argc = *pargc; 1.564 + 1.565 + /* To make things simpler we always copy the argv array */ 1.566 + newArgv = MemAlloc((argc + 1) * sizeof(char *)); 1.567 + 1.568 + /* The program name is always present */ 1.569 + newArgv[newArgvIdx++] = (*argv)[0]; 1.570 + 1.571 + for (argi = 1; argi < argc; argi++) { 1.572 + char *arg = (*argv)[argi]; 1.573 + isVMType = 0; 1.574 + 1.575 +#ifdef JAVA_ARGS 1.576 + if (arg[0] != '-') { 1.577 + newArgv[newArgvIdx++] = arg; 1.578 + continue; 1.579 + } 1.580 +#else 1.581 + if (strcmp(arg, "-classpath") == 0 || 1.582 + strcmp(arg, "-cp") == 0) { 1.583 + newArgv[newArgvIdx++] = arg; 1.584 + argi++; 1.585 + if (argi < argc) { 1.586 + newArgv[newArgvIdx++] = (*argv)[argi]; 1.587 + } 1.588 + continue; 1.589 + } 1.590 + if (arg[0] != '-') break; 1.591 +#endif 1.592 + 1.593 + /* Did the user pass an explicit VM type? */ 1.594 + i = KnownVMIndex(arg); 1.595 + if (i >= 0) { 1.596 + jvmtype = knownVMs[jvmidx = i].name + 1; /* skip the - */ 1.597 + isVMType = 1; 1.598 + *pargc = *pargc - 1; 1.599 + } 1.600 + 1.601 + /* Did the user specify an "alternate" VM? */ 1.602 + else if (strncmp(arg, "-XXaltjvm=", 10) == 0 || strncmp(arg, "-J-XXaltjvm=", 12) == 0) { 1.603 + isVMType = 1; 1.604 + jvmtype = arg+((arg[1]=='X')? 10 : 12); 1.605 + jvmidx = -1; 1.606 + } 1.607 + 1.608 + if (!isVMType) { 1.609 + newArgv[newArgvIdx++] = arg; 1.610 + } 1.611 + } 1.612 + 1.613 + /* 1.614 + * Finish copying the arguments if we aborted the above loop. 1.615 + * NOTE that if we aborted via "break" then we did NOT copy the 1.616 + * last argument above, and in addition argi will be less than 1.617 + * argc. 1.618 + */ 1.619 + while (argi < argc) { 1.620 + newArgv[newArgvIdx++] = (*argv)[argi]; 1.621 + argi++; 1.622 + } 1.623 + 1.624 + /* argv is null-terminated */ 1.625 + newArgv[newArgvIdx] = 0; 1.626 + 1.627 + /* Copy back argv */ 1.628 + *argv = newArgv; 1.629 + *pargc = newArgvIdx; 1.630 + 1.631 + /* use the default VM type if not specified (no alias processing) */ 1.632 + if (jvmtype == NULL) { 1.633 + char* result = knownVMs[0].name+1; 1.634 + /* Use a different VM type if we are on a server class machine? */ 1.635 + if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) && 1.636 + (ServerClassMachine() == JNI_TRUE)) { 1.637 + result = knownVMs[0].server_class+1; 1.638 + } 1.639 + if (_launcher_debug) { 1.640 + printf("Default VM: %s\n", result); 1.641 + } 1.642 + return result; 1.643 + } 1.644 + 1.645 + /* if using an alternate VM, no alias processing */ 1.646 + if (jvmidx < 0) 1.647 + return jvmtype; 1.648 + 1.649 + /* Resolve aliases first */ 1.650 + { 1.651 + int loopCount = 0; 1.652 + while (knownVMs[jvmidx].flag == VM_ALIASED_TO) { 1.653 + int nextIdx = KnownVMIndex(knownVMs[jvmidx].alias); 1.654 + 1.655 + if (loopCount > knownVMsCount) { 1.656 + if (!speculative) { 1.657 + ReportErrorMessage("Error: Corrupt jvm.cfg file; cycle in alias list.", 1.658 + JNI_TRUE); 1.659 + exit(1); 1.660 + } else { 1.661 + return "ERROR"; 1.662 + /* break; */ 1.663 + } 1.664 + } 1.665 + 1.666 + if (nextIdx < 0) { 1.667 + if (!speculative) { 1.668 + ReportErrorMessage2("Error: Unable to resolve VM alias %s", 1.669 + knownVMs[jvmidx].alias, JNI_TRUE); 1.670 + exit(1); 1.671 + } else { 1.672 + return "ERROR"; 1.673 + } 1.674 + } 1.675 + jvmidx = nextIdx; 1.676 + jvmtype = knownVMs[jvmidx].name+1; 1.677 + loopCount++; 1.678 + } 1.679 + } 1.680 + 1.681 + switch (knownVMs[jvmidx].flag) { 1.682 + case VM_WARN: 1.683 + if (!speculative) { 1.684 + fprintf(stderr, "Warning: %s VM not supported; %s VM will be used\n", 1.685 + jvmtype, knownVMs[0].name + 1); 1.686 + } 1.687 + /* fall through */ 1.688 + case VM_IGNORE: 1.689 + jvmtype = knownVMs[jvmidx=0].name + 1; 1.690 + /* fall through */ 1.691 + case VM_KNOWN: 1.692 + break; 1.693 + case VM_ERROR: 1.694 + if (!speculative) { 1.695 + ReportErrorMessage2("Error: %s VM not supported", jvmtype, JNI_TRUE); 1.696 + exit(1); 1.697 + } else { 1.698 + return "ERROR"; 1.699 + } 1.700 + } 1.701 + 1.702 + return jvmtype; 1.703 +} 1.704 +#endif /* ifndef GAMMA */ 1.705 + 1.706 +/* 1.707 + * Adds a new VM option with the given given name and value. 1.708 + */ 1.709 +static void 1.710 +AddOption(char *str, void *info) 1.711 +{ 1.712 + /* 1.713 + * Expand options array if needed to accommodate at least one more 1.714 + * VM option. 1.715 + */ 1.716 + if (numOptions >= maxOptions) { 1.717 + if (options == 0) { 1.718 + maxOptions = 4; 1.719 + options = MemAlloc(maxOptions * sizeof(JavaVMOption)); 1.720 + } else { 1.721 + JavaVMOption *tmp; 1.722 + maxOptions *= 2; 1.723 + tmp = MemAlloc(maxOptions * sizeof(JavaVMOption)); 1.724 + memcpy(tmp, options, numOptions * sizeof(JavaVMOption)); 1.725 + free(options); 1.726 + options = tmp; 1.727 + } 1.728 + } 1.729 + options[numOptions].optionString = str; 1.730 + options[numOptions++].extraInfo = info; 1.731 +} 1.732 + 1.733 +static void 1.734 +SetClassPath(char *s) 1.735 +{ 1.736 + char *def = MemAlloc(strlen(s) + 40); 1.737 + sprintf(def, "-Djava.class.path=%s", s); 1.738 + AddOption(def, NULL); 1.739 +} 1.740 + 1.741 +#ifndef GAMMA 1.742 +/* 1.743 + * The SelectVersion() routine ensures that an appropriate version of 1.744 + * the JRE is running. The specification for the appropriate version 1.745 + * is obtained from either the manifest of a jar file (preferred) or 1.746 + * from command line options. 1.747 + */ 1.748 +static void 1.749 +SelectVersion(int argc, char **argv, char **main_class) 1.750 +{ 1.751 + char *arg; 1.752 + char **new_argv; 1.753 + char **new_argp; 1.754 + char *operand; 1.755 + char *version = NULL; 1.756 + char *jre = NULL; 1.757 + int jarflag = 0; 1.758 + int restrict_search = -1; /* -1 implies not known */ 1.759 + manifest_info info; 1.760 + char env_entry[MAXNAMELEN + 24] = ENV_ENTRY "="; 1.761 + char *env_in; 1.762 + int res; 1.763 + 1.764 + /* 1.765 + * If the version has already been selected, set *main_class 1.766 + * with the value passed through the environment (if any) and 1.767 + * simply return. 1.768 + */ 1.769 + if ((env_in = getenv(ENV_ENTRY)) != NULL) { 1.770 + if (*env_in != '\0') 1.771 + *main_class = strdup(env_in); 1.772 + return; 1.773 + } 1.774 + 1.775 + /* 1.776 + * Scan through the arguments for options relevant to multiple JRE 1.777 + * support. For reference, the command line syntax is defined as: 1.778 + * 1.779 + * SYNOPSIS 1.780 + * java [options] class [argument...] 1.781 + * 1.782 + * java [options] -jar file.jar [argument...] 1.783 + * 1.784 + * As the scan is performed, make a copy of the argument list with 1.785 + * the version specification options (new to 1.5) removed, so that 1.786 + * a version less than 1.5 can be exec'd. 1.787 + */ 1.788 + new_argv = MemAlloc((argc + 1) * sizeof(char*)); 1.789 + new_argv[0] = argv[0]; 1.790 + new_argp = &new_argv[1]; 1.791 + argc--; 1.792 + argv++; 1.793 + while ((arg = *argv) != 0 && *arg == '-') { 1.794 + if (strncmp(arg, "-version:", 9) == 0) { 1.795 + version = arg + 9; 1.796 + } else if (strcmp(arg, "-jre-restrict-search") == 0) { 1.797 + restrict_search = 1; 1.798 + } else if (strcmp(arg, "-no-jre-restrict-search") == 0) { 1.799 + restrict_search = 0; 1.800 + } else { 1.801 + if (strcmp(arg, "-jar") == 0) 1.802 + jarflag = 1; 1.803 + /* deal with "unfortunate" classpath syntax */ 1.804 + if ((strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) && 1.805 + (argc >= 2)) { 1.806 + *new_argp++ = arg; 1.807 + argc--; 1.808 + argv++; 1.809 + arg = *argv; 1.810 + } 1.811 + *new_argp++ = arg; 1.812 + } 1.813 + argc--; 1.814 + argv++; 1.815 + } 1.816 + if (argc <= 0) { /* No operand? Possibly legit with -[full]version */ 1.817 + operand = NULL; 1.818 + } else { 1.819 + argc--; 1.820 + *new_argp++ = operand = *argv++; 1.821 + } 1.822 + while (argc-- > 0) /* Copy over [argument...] */ 1.823 + *new_argp++ = *argv++; 1.824 + *new_argp = NULL; 1.825 + 1.826 + /* 1.827 + * If there is a jar file, read the manifest. If the jarfile can't be 1.828 + * read, the manifest can't be read from the jar file, or the manifest 1.829 + * is corrupt, issue the appropriate error messages and exit. 1.830 + * 1.831 + * Even if there isn't a jar file, construct a manifest_info structure 1.832 + * containing the command line information. It's a convenient way to carry 1.833 + * this data around. 1.834 + */ 1.835 + if (jarflag && operand) { 1.836 + if ((res = parse_manifest(operand, &info)) != 0) { 1.837 + if (res == -1) 1.838 + ReportErrorMessage2("Unable to access jarfile %s", 1.839 + operand, JNI_TRUE); 1.840 + else 1.841 + ReportErrorMessage2("Invalid or corrupt jarfile %s", 1.842 + operand, JNI_TRUE); 1.843 + exit(1); 1.844 + } 1.845 + } else { 1.846 + info.manifest_version = NULL; 1.847 + info.main_class = NULL; 1.848 + info.jre_version = NULL; 1.849 + info.jre_restrict_search = 0; 1.850 + } 1.851 + 1.852 + /* 1.853 + * The JRE-Version and JRE-Restrict-Search values (if any) from the 1.854 + * manifest are overwritten by any specified on the command line. 1.855 + */ 1.856 + if (version != NULL) 1.857 + info.jre_version = version; 1.858 + if (restrict_search != -1) 1.859 + info.jre_restrict_search = restrict_search; 1.860 + 1.861 + /* 1.862 + * "Valid" returns (other than unrecoverable errors) follow. Set 1.863 + * main_class as a side-effect of this routine. 1.864 + */ 1.865 + if (info.main_class != NULL) 1.866 + *main_class = strdup(info.main_class); 1.867 + 1.868 + /* 1.869 + * If no version selection information is found either on the command 1.870 + * line or in the manifest, simply return. 1.871 + */ 1.872 + if (info.jre_version == NULL) { 1.873 + free_manifest(); 1.874 + free(new_argv); 1.875 + return; 1.876 + } 1.877 + 1.878 + /* 1.879 + * Check for correct syntax of the version specification (JSR 56). 1.880 + */ 1.881 + if (!valid_version_string(info.jre_version)) { 1.882 + ReportErrorMessage2("Syntax error in version specification \"%s\"", 1.883 + info.jre_version, JNI_TRUE); 1.884 + exit(1); 1.885 + } 1.886 + 1.887 + /* 1.888 + * Find the appropriate JVM on the system. Just to be as forgiving as 1.889 + * possible, if the standard algorithms don't locate an appropriate 1.890 + * jre, check to see if the one running will satisfy the requirements. 1.891 + * This can happen on systems which haven't been set-up for multiple 1.892 + * JRE support. 1.893 + */ 1.894 + jre = LocateJRE(&info); 1.895 + if (_launcher_debug) 1.896 + printf("JRE-Version = %s, JRE-Restrict-Search = %s Selected = %s\n", 1.897 + (info.jre_version?info.jre_version:"null"), 1.898 + (info.jre_restrict_search?"true":"false"), (jre?jre:"null")); 1.899 + if (jre == NULL) { 1.900 + if (acceptable_release(FULL_VERSION, info.jre_version)) { 1.901 + free_manifest(); 1.902 + free(new_argv); 1.903 + return; 1.904 + } else { 1.905 + ReportErrorMessage2( 1.906 + "Unable to locate JRE meeting specification \"%s\"", 1.907 + info.jre_version, JNI_TRUE); 1.908 + exit(1); 1.909 + } 1.910 + } 1.911 + 1.912 + /* 1.913 + * If I'm not the chosen one, exec the chosen one. Returning from 1.914 + * ExecJRE indicates that I am indeed the chosen one. 1.915 + * 1.916 + * The private environment variable _JAVA_VERSION_SET is used to 1.917 + * prevent the chosen one from re-reading the manifest file and 1.918 + * using the values found within to override the (potential) command 1.919 + * line flags stripped from argv (because the target may not 1.920 + * understand them). Passing the MainClass value is an optimization 1.921 + * to avoid locating, expanding and parsing the manifest extra 1.922 + * times. 1.923 + */ 1.924 + if (info.main_class != NULL) 1.925 + (void)strcat(env_entry, info.main_class); 1.926 + (void)putenv(env_entry); 1.927 + ExecJRE(jre, new_argv); 1.928 + free_manifest(); 1.929 + free(new_argv); 1.930 + return; 1.931 +} 1.932 +#endif /* ifndef GAMMA */ 1.933 + 1.934 +/* 1.935 + * Parses command line arguments. Returns JNI_FALSE if launcher 1.936 + * should exit without starting vm (e.g. certain version and usage 1.937 + * options); returns JNI_TRUE if vm needs to be started to process 1.938 + * given options. *pret (the launcher process return value) is set to 1.939 + * 0 for a normal exit. 1.940 + */ 1.941 +static jboolean 1.942 +ParseArguments(int *pargc, char ***pargv, char **pjarfile, 1.943 + char **pclassname, int *pret) 1.944 +{ 1.945 + int argc = *pargc; 1.946 + char **argv = *pargv; 1.947 + jboolean jarflag = JNI_FALSE; 1.948 + char *arg; 1.949 + 1.950 + *pret = 1; 1.951 + while ((arg = *argv) != 0 && *arg == '-') { 1.952 + argv++; --argc; 1.953 + if (strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) { 1.954 + if (argc < 1) { 1.955 + ReportErrorMessage2("%s requires class path specification", 1.956 + arg, JNI_TRUE); 1.957 + PrintUsage(); 1.958 + return JNI_FALSE; 1.959 + } 1.960 + SetClassPath(*argv); 1.961 + argv++; --argc; 1.962 + } else if (strcmp(arg, "-jar") == 0) { 1.963 + jarflag = JNI_TRUE; 1.964 + } else if (strcmp(arg, "-help") == 0 || 1.965 + strcmp(arg, "-h") == 0 || 1.966 + strcmp(arg, "-?") == 0) { 1.967 + PrintUsage(); 1.968 + *pret = 0; 1.969 + return JNI_FALSE; 1.970 + } else if (strcmp(arg, "-version") == 0) { 1.971 + printVersion = JNI_TRUE; 1.972 + return JNI_TRUE; 1.973 + } else if (strcmp(arg, "-showversion") == 0) { 1.974 + showVersion = JNI_TRUE; 1.975 + } else if (strcmp(arg, "-X") == 0) { 1.976 + *pret = PrintXUsage(); 1.977 + return JNI_FALSE; 1.978 +/* 1.979 + * The following case provide backward compatibility with old-style 1.980 + * command line options. 1.981 + */ 1.982 + } else if (strcmp(arg, "-fullversion") == 0) { 1.983 + fprintf(stderr, "%s full version \"%s\"\n", progname, 1.984 + FULL_VERSION); 1.985 + *pret = 0; 1.986 + return JNI_FALSE; 1.987 + } else if (strcmp(arg, "-verbosegc") == 0) { 1.988 + AddOption("-verbose:gc", NULL); 1.989 + } else if (strcmp(arg, "-t") == 0) { 1.990 + AddOption("-Xt", NULL); 1.991 + } else if (strcmp(arg, "-tm") == 0) { 1.992 + AddOption("-Xtm", NULL); 1.993 + } else if (strcmp(arg, "-debug") == 0) { 1.994 + AddOption("-Xdebug", NULL); 1.995 + } else if (strcmp(arg, "-noclassgc") == 0) { 1.996 + AddOption("-Xnoclassgc", NULL); 1.997 + } else if (strcmp(arg, "-Xfuture") == 0) { 1.998 + AddOption("-Xverify:all", NULL); 1.999 + } else if (strcmp(arg, "-verify") == 0) { 1.1000 + AddOption("-Xverify:all", NULL); 1.1001 + } else if (strcmp(arg, "-verifyremote") == 0) { 1.1002 + AddOption("-Xverify:remote", NULL); 1.1003 + } else if (strcmp(arg, "-noverify") == 0) { 1.1004 + AddOption("-Xverify:none", NULL); 1.1005 + } else if (strcmp(arg, "-XXsuppressExitMessage") == 0) { 1.1006 + noExitErrorMessage = 1; 1.1007 + } else if (strncmp(arg, "-prof", 5) == 0) { 1.1008 + char *p = arg + 5; 1.1009 + char *tmp = MemAlloc(strlen(arg) + 50); 1.1010 + if (*p) { 1.1011 + sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1); 1.1012 + } else { 1.1013 + sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof"); 1.1014 + } 1.1015 + AddOption(tmp, NULL); 1.1016 + } else if (strncmp(arg, "-ss", 3) == 0 || 1.1017 + strncmp(arg, "-oss", 4) == 0 || 1.1018 + strncmp(arg, "-ms", 3) == 0 || 1.1019 + strncmp(arg, "-mx", 3) == 0) { 1.1020 + char *tmp = MemAlloc(strlen(arg) + 6); 1.1021 + sprintf(tmp, "-X%s", arg + 1); /* skip '-' */ 1.1022 + AddOption(tmp, NULL); 1.1023 + } else if (strcmp(arg, "-checksource") == 0 || 1.1024 + strcmp(arg, "-cs") == 0 || 1.1025 + strcmp(arg, "-noasyncgc") == 0) { 1.1026 + /* No longer supported */ 1.1027 + fprintf(stderr, 1.1028 + "Warning: %s option is no longer supported.\n", 1.1029 + arg); 1.1030 + } else if (strncmp(arg, "-version:", 9) == 0 || 1.1031 + strcmp(arg, "-no-jre-restrict-search") == 0 || 1.1032 + strcmp(arg, "-jre-restrict-search") == 0) { 1.1033 + ; /* Ignore machine independent options already handled */ 1.1034 + } else if (RemovableMachineDependentOption(arg) ) { 1.1035 + ; /* Do not pass option to vm. */ 1.1036 + } 1.1037 + else { 1.1038 + AddOption(arg, NULL); 1.1039 + } 1.1040 + } 1.1041 + 1.1042 + if (--argc >= 0) { 1.1043 + if (jarflag) { 1.1044 + *pjarfile = *argv++; 1.1045 + *pclassname = 0; 1.1046 + } else { 1.1047 + *pjarfile = 0; 1.1048 + *pclassname = *argv++; 1.1049 + } 1.1050 + *pargc = argc; 1.1051 + *pargv = argv; 1.1052 + } 1.1053 + 1.1054 + return JNI_TRUE; 1.1055 +} 1.1056 + 1.1057 +/* 1.1058 + * Initializes the Java Virtual Machine. Also frees options array when 1.1059 + * finished. 1.1060 + */ 1.1061 +static jboolean 1.1062 +InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn) 1.1063 +{ 1.1064 + JavaVMInitArgs args; 1.1065 + jint r; 1.1066 + 1.1067 + memset(&args, 0, sizeof(args)); 1.1068 + args.version = JNI_VERSION_1_2; 1.1069 + args.nOptions = numOptions; 1.1070 + args.options = options; 1.1071 + args.ignoreUnrecognized = JNI_FALSE; 1.1072 + 1.1073 + if (_launcher_debug) { 1.1074 + int i = 0; 1.1075 + printf("JavaVM args:\n "); 1.1076 + printf("version 0x%08lx, ", (long)args.version); 1.1077 + printf("ignoreUnrecognized is %s, ", 1.1078 + args.ignoreUnrecognized ? "JNI_TRUE" : "JNI_FALSE"); 1.1079 + printf("nOptions is %ld\n", (long)args.nOptions); 1.1080 + for (i = 0; i < numOptions; i++) 1.1081 + printf(" option[%2d] = '%s'\n", 1.1082 + i, args.options[i].optionString); 1.1083 + } 1.1084 + 1.1085 + r = ifn->CreateJavaVM(pvm, (void **)penv, &args); 1.1086 + free(options); 1.1087 + return r == JNI_OK; 1.1088 +} 1.1089 + 1.1090 + 1.1091 +#define NULL_CHECK0(e) if ((e) == 0) return 0 1.1092 +#define NULL_CHECK(e) if ((e) == 0) return 1.1093 + 1.1094 +/* 1.1095 + * Returns a pointer to a block of at least 'size' bytes of memory. 1.1096 + * Prints error message and exits if the memory could not be allocated. 1.1097 + */ 1.1098 +void * 1.1099 +MemAlloc(size_t size) 1.1100 +{ 1.1101 + void *p = malloc(size); 1.1102 + if (p == 0) { 1.1103 + perror("malloc"); 1.1104 + exit(1); 1.1105 + } 1.1106 + return p; 1.1107 +} 1.1108 + 1.1109 +static jstring platformEncoding = NULL; 1.1110 +static jstring getPlatformEncoding(JNIEnv *env) { 1.1111 + if (platformEncoding == NULL) { 1.1112 + jstring propname = (*env)->NewStringUTF(env, "sun.jnu.encoding"); 1.1113 + if (propname) { 1.1114 + jclass cls; 1.1115 + jmethodID mid; 1.1116 + NULL_CHECK0 (cls = (*env)->FindClass(env, "java/lang/System")); 1.1117 + NULL_CHECK0 (mid = (*env)->GetStaticMethodID( 1.1118 + env, cls, 1.1119 + "getProperty", 1.1120 + "(Ljava/lang/String;)Ljava/lang/String;")); 1.1121 + platformEncoding = (*env)->CallStaticObjectMethod ( 1.1122 + env, cls, mid, propname); 1.1123 + } 1.1124 + } 1.1125 + return platformEncoding; 1.1126 +} 1.1127 + 1.1128 +static jboolean isEncodingSupported(JNIEnv *env, jstring enc) { 1.1129 + jclass cls; 1.1130 + jmethodID mid; 1.1131 + NULL_CHECK0 (cls = (*env)->FindClass(env, "java/nio/charset/Charset")); 1.1132 + NULL_CHECK0 (mid = (*env)->GetStaticMethodID( 1.1133 + env, cls, 1.1134 + "isSupported", 1.1135 + "(Ljava/lang/String;)Z")); 1.1136 + return (jboolean)(*env)->CallStaticObjectMethod (env, cls, mid, enc); 1.1137 +} 1.1138 + 1.1139 +/* 1.1140 + * Returns a new Java string object for the specified platform string. 1.1141 + */ 1.1142 +static jstring 1.1143 +NewPlatformString(JNIEnv *env, char *s) 1.1144 +{ 1.1145 + int len = (int)strlen(s); 1.1146 + jclass cls; 1.1147 + jmethodID mid; 1.1148 + jbyteArray ary; 1.1149 + jstring enc; 1.1150 + 1.1151 + if (s == NULL) 1.1152 + return 0; 1.1153 + enc = getPlatformEncoding(env); 1.1154 + 1.1155 + ary = (*env)->NewByteArray(env, len); 1.1156 + if (ary != 0) { 1.1157 + jstring str = 0; 1.1158 + (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s); 1.1159 + if (!(*env)->ExceptionOccurred(env)) { 1.1160 +#ifdef GAMMA 1.1161 + /* We support running JVM with older JDK, so here we have to deal */ 1.1162 + /* with the case that sun.jnu.encoding is undefined (enc == NULL) */ 1.1163 + if (enc != NULL && isEncodingSupported(env, enc) == JNI_TRUE) { 1.1164 +#else 1.1165 + if (isEncodingSupported(env, enc) == JNI_TRUE) { 1.1166 +#endif 1.1167 + NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); 1.1168 + NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>", 1.1169 + "([BLjava/lang/String;)V")); 1.1170 + str = (*env)->NewObject(env, cls, mid, ary, enc); 1.1171 + } else { 1.1172 + /*If the encoding specified in sun.jnu.encoding is not 1.1173 + endorsed by "Charset.isSupported" we have to fall back 1.1174 + to use String(byte[]) explicitly here without specifying 1.1175 + the encoding name, in which the StringCoding class will 1.1176 + pickup the iso-8859-1 as the fallback converter for us. 1.1177 + */ 1.1178 + NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); 1.1179 + NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>", 1.1180 + "([B)V")); 1.1181 + str = (*env)->NewObject(env, cls, mid, ary); 1.1182 + } 1.1183 + (*env)->DeleteLocalRef(env, ary); 1.1184 + return str; 1.1185 + } 1.1186 + } 1.1187 + return 0; 1.1188 +} 1.1189 + 1.1190 +/* 1.1191 + * Returns a new array of Java string objects for the specified 1.1192 + * array of platform strings. 1.1193 + */ 1.1194 +static jobjectArray 1.1195 +NewPlatformStringArray(JNIEnv *env, char **strv, int strc) 1.1196 +{ 1.1197 + jarray cls; 1.1198 + jarray ary; 1.1199 + int i; 1.1200 + 1.1201 + NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); 1.1202 + NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0)); 1.1203 + for (i = 0; i < strc; i++) { 1.1204 + jstring str = NewPlatformString(env, *strv++); 1.1205 + NULL_CHECK0(str); 1.1206 + (*env)->SetObjectArrayElement(env, ary, i, str); 1.1207 + (*env)->DeleteLocalRef(env, str); 1.1208 + } 1.1209 + return ary; 1.1210 +} 1.1211 + 1.1212 +/* 1.1213 + * Loads a class, convert the '.' to '/'. 1.1214 + */ 1.1215 +static jclass 1.1216 +LoadClass(JNIEnv *env, char *name) 1.1217 +{ 1.1218 + char *buf = MemAlloc(strlen(name) + 1); 1.1219 + char *s = buf, *t = name, c; 1.1220 + jclass cls; 1.1221 + jlong start, end; 1.1222 + 1.1223 + if (_launcher_debug) 1.1224 + start = CounterGet(); 1.1225 + 1.1226 + do { 1.1227 + c = *t++; 1.1228 + *s++ = (c == '.') ? '/' : c; 1.1229 + } while (c != '\0'); 1.1230 + cls = (*env)->FindClass(env, buf); 1.1231 + free(buf); 1.1232 + 1.1233 + if (_launcher_debug) { 1.1234 + end = CounterGet(); 1.1235 + printf("%ld micro seconds to load main class\n", 1.1236 + (long)(jint)Counter2Micros(end-start)); 1.1237 + printf("----_JAVA_LAUNCHER_DEBUG----\n"); 1.1238 + } 1.1239 + 1.1240 + return cls; 1.1241 +} 1.1242 + 1.1243 + 1.1244 +/* 1.1245 + * Returns the main class name for the specified jar file. 1.1246 + */ 1.1247 +static jstring 1.1248 +GetMainClassName(JNIEnv *env, char *jarname) 1.1249 +{ 1.1250 +#define MAIN_CLASS "Main-Class" 1.1251 + jclass cls; 1.1252 + jmethodID mid; 1.1253 + jobject jar, man, attr; 1.1254 + jstring str, result = 0; 1.1255 + 1.1256 + NULL_CHECK0(cls = (*env)->FindClass(env, "java/util/jar/JarFile")); 1.1257 + NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>", 1.1258 + "(Ljava/lang/String;)V")); 1.1259 + NULL_CHECK0(str = NewPlatformString(env, jarname)); 1.1260 + NULL_CHECK0(jar = (*env)->NewObject(env, cls, mid, str)); 1.1261 + NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "getManifest", 1.1262 + "()Ljava/util/jar/Manifest;")); 1.1263 + man = (*env)->CallObjectMethod(env, jar, mid); 1.1264 + if (man != 0) { 1.1265 + NULL_CHECK0(mid = (*env)->GetMethodID(env, 1.1266 + (*env)->GetObjectClass(env, man), 1.1267 + "getMainAttributes", 1.1268 + "()Ljava/util/jar/Attributes;")); 1.1269 + attr = (*env)->CallObjectMethod(env, man, mid); 1.1270 + if (attr != 0) { 1.1271 + NULL_CHECK0(mid = (*env)->GetMethodID(env, 1.1272 + (*env)->GetObjectClass(env, attr), 1.1273 + "getValue", 1.1274 + "(Ljava/lang/String;)Ljava/lang/String;")); 1.1275 + NULL_CHECK0(str = NewPlatformString(env, MAIN_CLASS)); 1.1276 + result = (*env)->CallObjectMethod(env, attr, mid, str); 1.1277 + } 1.1278 + } 1.1279 + return result; 1.1280 +} 1.1281 + 1.1282 +#ifdef JAVA_ARGS 1.1283 +static char *java_args[] = JAVA_ARGS; 1.1284 +static char *app_classpath[] = APP_CLASSPATH; 1.1285 + 1.1286 +/* 1.1287 + * For tools convert 'javac -J-ms32m' to 'java -ms32m ...' 1.1288 + */ 1.1289 +static void 1.1290 +TranslateDashJArgs(int *pargc, char ***pargv) 1.1291 +{ 1.1292 + const int NUM_ARGS = (sizeof(java_args) / sizeof(char *)); 1.1293 + int argc = *pargc; 1.1294 + char **argv = *pargv; 1.1295 + int nargc = argc + NUM_ARGS; 1.1296 + char **nargv = MemAlloc((nargc + 1) * sizeof(char *)); 1.1297 + int i; 1.1298 + 1.1299 + *pargc = nargc; 1.1300 + *pargv = nargv; 1.1301 + 1.1302 + /* Copy the VM arguments (i.e. prefixed with -J) */ 1.1303 + for (i = 0; i < NUM_ARGS; i++) { 1.1304 + char *arg = java_args[i]; 1.1305 + if (arg[0] == '-' && arg[1] == 'J') { 1.1306 + *nargv++ = arg + 2; 1.1307 + } 1.1308 + } 1.1309 + 1.1310 + for (i = 0; i < argc; i++) { 1.1311 + char *arg = argv[i]; 1.1312 + if (arg[0] == '-' && arg[1] == 'J') { 1.1313 + if (arg[2] == '\0') { 1.1314 + ReportErrorMessage("Error: the -J option should not be " 1.1315 + "followed by a space.", JNI_TRUE); 1.1316 + exit(1); 1.1317 + } 1.1318 + *nargv++ = arg + 2; 1.1319 + } 1.1320 + } 1.1321 + 1.1322 + /* Copy the rest of the arguments */ 1.1323 + for (i = 0; i < NUM_ARGS; i++) { 1.1324 + char *arg = java_args[i]; 1.1325 + if (arg[0] != '-' || arg[1] != 'J') { 1.1326 + *nargv++ = arg; 1.1327 + } 1.1328 + } 1.1329 + for (i = 0; i < argc; i++) { 1.1330 + char *arg = argv[i]; 1.1331 + if (arg[0] != '-' || arg[1] != 'J') { 1.1332 + *nargv++ = arg; 1.1333 + } 1.1334 + } 1.1335 + *nargv = 0; 1.1336 +} 1.1337 + 1.1338 +/* 1.1339 + * For our tools, we try to add 3 VM options: 1.1340 + * -Denv.class.path=<envcp> 1.1341 + * -Dapplication.home=<apphome> 1.1342 + * -Djava.class.path=<appcp> 1.1343 + * <envcp> is the user's setting of CLASSPATH -- for instance the user 1.1344 + * tells javac where to find binary classes through this environment 1.1345 + * variable. Notice that users will be able to compile against our 1.1346 + * tools classes (sun.tools.javac.Main) only if they explicitly add 1.1347 + * tools.jar to CLASSPATH. 1.1348 + * <apphome> is the directory where the application is installed. 1.1349 + * <appcp> is the classpath to where our apps' classfiles are. 1.1350 + */ 1.1351 +static jboolean 1.1352 +AddApplicationOptions() 1.1353 +{ 1.1354 + const int NUM_APP_CLASSPATH = (sizeof(app_classpath) / sizeof(char *)); 1.1355 + char *s, *envcp, *appcp, *apphome; 1.1356 + char home[MAXPATHLEN]; /* application home */ 1.1357 + char separator[] = { PATH_SEPARATOR, '\0' }; 1.1358 + int size, i; 1.1359 + int strlenHome; 1.1360 + 1.1361 + s = getenv("CLASSPATH"); 1.1362 + if (s) { 1.1363 + /* 40 for -Denv.class.path= */ 1.1364 + envcp = (char *)MemAlloc(strlen(s) + 40); 1.1365 + sprintf(envcp, "-Denv.class.path=%s", s); 1.1366 + AddOption(envcp, NULL); 1.1367 + } 1.1368 + 1.1369 + if (!GetApplicationHome(home, sizeof(home))) { 1.1370 + ReportErrorMessage("Can't determine application home", JNI_TRUE); 1.1371 + return JNI_FALSE; 1.1372 + } 1.1373 + 1.1374 + /* 40 for '-Dapplication.home=' */ 1.1375 + apphome = (char *)MemAlloc(strlen(home) + 40); 1.1376 + sprintf(apphome, "-Dapplication.home=%s", home); 1.1377 + AddOption(apphome, NULL); 1.1378 + 1.1379 + /* How big is the application's classpath? */ 1.1380 + size = 40; /* 40: "-Djava.class.path=" */ 1.1381 + strlenHome = (int)strlen(home); 1.1382 + for (i = 0; i < NUM_APP_CLASSPATH; i++) { 1.1383 + size += strlenHome + (int)strlen(app_classpath[i]) + 1; /* 1: separator */ 1.1384 + } 1.1385 + appcp = (char *)MemAlloc(size + 1); 1.1386 + strcpy(appcp, "-Djava.class.path="); 1.1387 + for (i = 0; i < NUM_APP_CLASSPATH; i++) { 1.1388 + strcat(appcp, home); /* c:\program files\myapp */ 1.1389 + strcat(appcp, app_classpath[i]); /* \lib\myapp.jar */ 1.1390 + strcat(appcp, separator); /* ; */ 1.1391 + } 1.1392 + appcp[strlen(appcp)-1] = '\0'; /* remove trailing path separator */ 1.1393 + AddOption(appcp, NULL); 1.1394 + return JNI_TRUE; 1.1395 +} 1.1396 +#endif 1.1397 + 1.1398 +/* 1.1399 + * inject the -Dsun.java.command pseudo property into the args structure 1.1400 + * this pseudo property is used in the HotSpot VM to expose the 1.1401 + * Java class name and arguments to the main method to the VM. The 1.1402 + * HotSpot VM uses this pseudo property to store the Java class name 1.1403 + * (or jar file name) and the arguments to the class's main method 1.1404 + * to the instrumentation memory region. The sun.java.command pseudo 1.1405 + * property is not exported by HotSpot to the Java layer. 1.1406 + */ 1.1407 +void 1.1408 +SetJavaCommandLineProp(char *classname, char *jarfile, 1.1409 + int argc, char **argv) 1.1410 +{ 1.1411 + 1.1412 + int i = 0; 1.1413 + size_t len = 0; 1.1414 + char* javaCommand = NULL; 1.1415 + char* dashDstr = "-Dsun.java.command="; 1.1416 + 1.1417 + if (classname == NULL && jarfile == NULL) { 1.1418 + /* unexpected, one of these should be set. just return without 1.1419 + * setting the property 1.1420 + */ 1.1421 + return; 1.1422 + } 1.1423 + 1.1424 + /* if the class name is not set, then use the jarfile name */ 1.1425 + if (classname == NULL) { 1.1426 + classname = jarfile; 1.1427 + } 1.1428 + 1.1429 + /* determine the amount of memory to allocate assuming 1.1430 + * the individual components will be space separated 1.1431 + */ 1.1432 + len = strlen(classname); 1.1433 + for (i = 0; i < argc; i++) { 1.1434 + len += strlen(argv[i]) + 1; 1.1435 + } 1.1436 + 1.1437 + /* allocate the memory */ 1.1438 + javaCommand = (char*) MemAlloc(len + strlen(dashDstr) + 1); 1.1439 + 1.1440 + /* build the -D string */ 1.1441 + *javaCommand = '\0'; 1.1442 + strcat(javaCommand, dashDstr); 1.1443 + strcat(javaCommand, classname); 1.1444 + 1.1445 + for (i = 0; i < argc; i++) { 1.1446 + /* the components of the string are space separated. In 1.1447 + * the case of embedded white space, the relationship of 1.1448 + * the white space separated components to their true 1.1449 + * positional arguments will be ambiguous. This issue may 1.1450 + * be addressed in a future release. 1.1451 + */ 1.1452 + strcat(javaCommand, " "); 1.1453 + strcat(javaCommand, argv[i]); 1.1454 + } 1.1455 + 1.1456 + AddOption(javaCommand, NULL); 1.1457 +} 1.1458 + 1.1459 +/* 1.1460 + * JVM wants to know launcher type, so tell it. 1.1461 + */ 1.1462 +#ifdef GAMMA 1.1463 +void SetJavaLauncherProp() { 1.1464 + AddOption("-Dsun.java.launcher=" LAUNCHER_TYPE, NULL); 1.1465 +} 1.1466 +#endif 1.1467 + 1.1468 +/* 1.1469 + * Prints the version information from the java.version and other properties. 1.1470 + */ 1.1471 +static void 1.1472 +PrintJavaVersion(JNIEnv *env) 1.1473 +{ 1.1474 + jclass ver; 1.1475 + jmethodID print; 1.1476 + 1.1477 + NULL_CHECK(ver = (*env)->FindClass(env, "sun/misc/Version")); 1.1478 + NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, "print", "()V")); 1.1479 + 1.1480 + (*env)->CallStaticVoidMethod(env, ver, print); 1.1481 +} 1.1482 + 1.1483 +/* 1.1484 + * Prints default usage message. 1.1485 + */ 1.1486 +static void 1.1487 +PrintUsage(void) 1.1488 +{ 1.1489 + int i; 1.1490 + 1.1491 + fprintf(stdout, 1.1492 + "Usage: %s [-options] class [args...]\n" 1.1493 + " (to execute a class)\n" 1.1494 + " or %s [-options] -jar jarfile [args...]\n" 1.1495 + " (to execute a jar file)\n" 1.1496 + "\n" 1.1497 + "where options include:\n", 1.1498 + progname, 1.1499 + progname); 1.1500 + 1.1501 +#ifndef GAMMA 1.1502 + PrintMachineDependentOptions(); 1.1503 + 1.1504 + if ((knownVMs[0].flag == VM_KNOWN) || 1.1505 + (knownVMs[0].flag == VM_IF_SERVER_CLASS)) { 1.1506 + fprintf(stdout, " %s\t to select the \"%s\" VM\n", 1.1507 + knownVMs[0].name, knownVMs[0].name+1); 1.1508 + } 1.1509 + for (i=1; i<knownVMsCount; i++) { 1.1510 + if (knownVMs[i].flag == VM_KNOWN) 1.1511 + fprintf(stdout, " %s\t to select the \"%s\" VM\n", 1.1512 + knownVMs[i].name, knownVMs[i].name+1); 1.1513 + } 1.1514 + for (i=1; i<knownVMsCount; i++) { 1.1515 + if (knownVMs[i].flag == VM_ALIASED_TO) 1.1516 + fprintf(stdout, " %s\t is a synonym for " 1.1517 + "the \"%s\" VM [deprecated]\n", 1.1518 + knownVMs[i].name, knownVMs[i].alias+1); 1.1519 + } 1.1520 + 1.1521 + /* The first known VM is the default */ 1.1522 + { 1.1523 + const char* defaultVM = knownVMs[0].name+1; 1.1524 + const char* punctuation = "."; 1.1525 + const char* reason = ""; 1.1526 + if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) && 1.1527 + (ServerClassMachine() == JNI_TRUE)) { 1.1528 + defaultVM = knownVMs[0].server_class+1; 1.1529 + punctuation = ", "; 1.1530 + reason = "because you are running on a server-class machine.\n"; 1.1531 + } 1.1532 + fprintf(stdout, " The default VM is %s%s\n", 1.1533 + defaultVM, punctuation); 1.1534 + fprintf(stdout, " %s\n", 1.1535 + reason); 1.1536 + } 1.1537 +#endif /* ifndef GAMMA */ 1.1538 + 1.1539 + fprintf(stdout, 1.1540 +" -cp <class search path of directories and zip/jar files>\n" 1.1541 +" -classpath <class search path of directories and zip/jar files>\n" 1.1542 +" A %c separated list of directories, JAR archives,\n" 1.1543 +" and ZIP archives to search for class files.\n" 1.1544 +" -D<name>=<value>\n" 1.1545 +" set a system property\n" 1.1546 +" -verbose[:class|gc|jni]\n" 1.1547 +" enable verbose output\n" 1.1548 +" -version print product version and exit\n" 1.1549 +" -version:<value>\n" 1.1550 +" require the specified version to run\n" 1.1551 +" -showversion print product version and continue\n" 1.1552 +" -jre-restrict-search | -jre-no-restrict-search\n" 1.1553 +" include/exclude user private JREs in the version search\n" 1.1554 +" -? -help print this help message\n" 1.1555 +" -X print help on non-standard options\n" 1.1556 +" -ea[:<packagename>...|:<classname>]\n" 1.1557 +" -enableassertions[:<packagename>...|:<classname>]\n" 1.1558 +" enable assertions\n" 1.1559 +" -da[:<packagename>...|:<classname>]\n" 1.1560 +" -disableassertions[:<packagename>...|:<classname>]\n" 1.1561 +" disable assertions\n" 1.1562 +" -esa | -enablesystemassertions\n" 1.1563 +" enable system assertions\n" 1.1564 +" -dsa | -disablesystemassertions\n" 1.1565 +" disable system assertions\n" 1.1566 +" -agentlib:<libname>[=<options>]\n" 1.1567 +" load native agent library <libname>, e.g. -agentlib:hprof\n" 1.1568 +" see also, -agentlib:jdwp=help and -agentlib:hprof=help\n" 1.1569 +" -agentpath:<pathname>[=<options>]\n" 1.1570 +" load native agent library by full pathname\n" 1.1571 +" -javaagent:<jarpath>[=<options>]\n" 1.1572 +" load Java programming language agent, see java.lang.instrument\n" 1.1573 + 1.1574 + ,PATH_SEPARATOR); 1.1575 +} 1.1576 + 1.1577 +/* 1.1578 + * Print usage message for -X options. 1.1579 + */ 1.1580 +static jint 1.1581 +PrintXUsage(void) 1.1582 +{ 1.1583 + char path[MAXPATHLEN]; 1.1584 + char buf[128]; 1.1585 + size_t n; 1.1586 + FILE *fp; 1.1587 + 1.1588 + GetXUsagePath(path, sizeof(path)); 1.1589 + fp = fopen(path, "r"); 1.1590 + if (fp == 0) { 1.1591 + fprintf(stderr, "Can't open %s\n", path); 1.1592 + return 1; 1.1593 + } 1.1594 + while ((n = fread(buf, 1, sizeof(buf), fp)) != 0) { 1.1595 + fwrite(buf, 1, n, stdout); 1.1596 + } 1.1597 + fclose(fp); 1.1598 + return 0; 1.1599 +} 1.1600 + 1.1601 +#ifndef GAMMA 1.1602 + 1.1603 +/* 1.1604 + * Read the jvm.cfg file and fill the knownJVMs[] array. 1.1605 + * 1.1606 + * The functionality of the jvm.cfg file is subject to change without 1.1607 + * notice and the mechanism will be removed in the future. 1.1608 + * 1.1609 + * The lexical structure of the jvm.cfg file is as follows: 1.1610 + * 1.1611 + * jvmcfg := { vmLine } 1.1612 + * vmLine := knownLine 1.1613 + * | aliasLine 1.1614 + * | warnLine 1.1615 + * | ignoreLine 1.1616 + * | errorLine 1.1617 + * | predicateLine 1.1618 + * | commentLine 1.1619 + * knownLine := flag "KNOWN" EOL 1.1620 + * warnLine := flag "WARN" EOL 1.1621 + * ignoreLine := flag "IGNORE" EOL 1.1622 + * errorLine := flag "ERROR" EOL 1.1623 + * aliasLine := flag "ALIASED_TO" flag EOL 1.1624 + * predicateLine := flag "IF_SERVER_CLASS" flag EOL 1.1625 + * commentLine := "#" text EOL 1.1626 + * flag := "-" identifier 1.1627 + * 1.1628 + * The semantics are that when someone specifies a flag on the command line: 1.1629 + * - if the flag appears on a knownLine, then the identifier is used as 1.1630 + * the name of the directory holding the JVM library (the name of the JVM). 1.1631 + * - if the flag appears as the first flag on an aliasLine, the identifier 1.1632 + * of the second flag is used as the name of the JVM. 1.1633 + * - if the flag appears on a warnLine, the identifier is used as the 1.1634 + * name of the JVM, but a warning is generated. 1.1635 + * - if the flag appears on an ignoreLine, the identifier is recognized as the 1.1636 + * name of a JVM, but the identifier is ignored and the default vm used 1.1637 + * - if the flag appears on an errorLine, an error is generated. 1.1638 + * - if the flag appears as the first flag on a predicateLine, and 1.1639 + * the machine on which you are running passes the predicate indicated, 1.1640 + * then the identifier of the second flag is used as the name of the JVM, 1.1641 + * otherwise the identifier of the first flag is used as the name of the JVM. 1.1642 + * If no flag is given on the command line, the first vmLine of the jvm.cfg 1.1643 + * file determines the name of the JVM. 1.1644 + * PredicateLines are only interpreted on first vmLine of a jvm.cfg file, 1.1645 + * since they only make sense if someone hasn't specified the name of the 1.1646 + * JVM on the command line. 1.1647 + * 1.1648 + * The intent of the jvm.cfg file is to allow several JVM libraries to 1.1649 + * be installed in different subdirectories of a single JRE installation, 1.1650 + * for space-savings and convenience in testing. 1.1651 + * The intent is explicitly not to provide a full aliasing or predicate 1.1652 + * mechanism. 1.1653 + */ 1.1654 +jint 1.1655 +ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative) 1.1656 +{ 1.1657 + FILE *jvmCfg; 1.1658 + char jvmCfgName[MAXPATHLEN+20]; 1.1659 + char line[MAXPATHLEN+20]; 1.1660 + int cnt = 0; 1.1661 + int lineno = 0; 1.1662 + jlong start, end; 1.1663 + int vmType; 1.1664 + char *tmpPtr; 1.1665 + char *altVMName; 1.1666 + char *serverClassVMName; 1.1667 + static char *whiteSpace = " \t"; 1.1668 + if (_launcher_debug) { 1.1669 + start = CounterGet(); 1.1670 + } 1.1671 + 1.1672 + strcpy(jvmCfgName, jrepath); 1.1673 + strcat(jvmCfgName, FILESEP "lib" FILESEP); 1.1674 + strcat(jvmCfgName, arch); 1.1675 + strcat(jvmCfgName, FILESEP "jvm.cfg"); 1.1676 + 1.1677 + jvmCfg = fopen(jvmCfgName, "r"); 1.1678 + if (jvmCfg == NULL) { 1.1679 + if (!speculative) { 1.1680 + ReportErrorMessage2("Error: could not open `%s'", jvmCfgName, 1.1681 + JNI_TRUE); 1.1682 + exit(1); 1.1683 + } else { 1.1684 + return -1; 1.1685 + } 1.1686 + } 1.1687 + while (fgets(line, sizeof(line), jvmCfg) != NULL) { 1.1688 + vmType = VM_UNKNOWN; 1.1689 + lineno++; 1.1690 + if (line[0] == '#') 1.1691 + continue; 1.1692 + if (line[0] != '-') { 1.1693 + fprintf(stderr, "Warning: no leading - on line %d of `%s'\n", 1.1694 + lineno, jvmCfgName); 1.1695 + } 1.1696 + if (cnt >= knownVMsLimit) { 1.1697 + GrowKnownVMs(cnt); 1.1698 + } 1.1699 + line[strlen(line)-1] = '\0'; /* remove trailing newline */ 1.1700 + tmpPtr = line + strcspn(line, whiteSpace); 1.1701 + if (*tmpPtr == 0) { 1.1702 + fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n", 1.1703 + lineno, jvmCfgName); 1.1704 + } else { 1.1705 + /* Null-terminate this string for strdup below */ 1.1706 + *tmpPtr++ = 0; 1.1707 + tmpPtr += strspn(tmpPtr, whiteSpace); 1.1708 + if (*tmpPtr == 0) { 1.1709 + fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n", 1.1710 + lineno, jvmCfgName); 1.1711 + } else { 1.1712 + if (!strncmp(tmpPtr, "KNOWN", strlen("KNOWN"))) { 1.1713 + vmType = VM_KNOWN; 1.1714 + } else if (!strncmp(tmpPtr, "ALIASED_TO", strlen("ALIASED_TO"))) { 1.1715 + tmpPtr += strcspn(tmpPtr, whiteSpace); 1.1716 + if (*tmpPtr != 0) { 1.1717 + tmpPtr += strspn(tmpPtr, whiteSpace); 1.1718 + } 1.1719 + if (*tmpPtr == 0) { 1.1720 + fprintf(stderr, "Warning: missing VM alias on line %d of `%s'\n", 1.1721 + lineno, jvmCfgName); 1.1722 + } else { 1.1723 + /* Null terminate altVMName */ 1.1724 + altVMName = tmpPtr; 1.1725 + tmpPtr += strcspn(tmpPtr, whiteSpace); 1.1726 + *tmpPtr = 0; 1.1727 + vmType = VM_ALIASED_TO; 1.1728 + } 1.1729 + } else if (!strncmp(tmpPtr, "WARN", strlen("WARN"))) { 1.1730 + vmType = VM_WARN; 1.1731 + } else if (!strncmp(tmpPtr, "IGNORE", strlen("IGNORE"))) { 1.1732 + vmType = VM_IGNORE; 1.1733 + } else if (!strncmp(tmpPtr, "ERROR", strlen("ERROR"))) { 1.1734 + vmType = VM_ERROR; 1.1735 + } else if (!strncmp(tmpPtr, 1.1736 + "IF_SERVER_CLASS", 1.1737 + strlen("IF_SERVER_CLASS"))) { 1.1738 + tmpPtr += strcspn(tmpPtr, whiteSpace); 1.1739 + if (*tmpPtr != 0) { 1.1740 + tmpPtr += strspn(tmpPtr, whiteSpace); 1.1741 + } 1.1742 + if (*tmpPtr == 0) { 1.1743 + fprintf(stderr, "Warning: missing server class VM on line %d of `%s'\n", 1.1744 + lineno, jvmCfgName); 1.1745 + } else { 1.1746 + /* Null terminate server class VM name */ 1.1747 + serverClassVMName = tmpPtr; 1.1748 + tmpPtr += strcspn(tmpPtr, whiteSpace); 1.1749 + *tmpPtr = 0; 1.1750 + vmType = VM_IF_SERVER_CLASS; 1.1751 + } 1.1752 + } else { 1.1753 + fprintf(stderr, "Warning: unknown VM type on line %d of `%s'\n", 1.1754 + lineno, &jvmCfgName[0]); 1.1755 + vmType = VM_KNOWN; 1.1756 + } 1.1757 + } 1.1758 + } 1.1759 + 1.1760 + if (_launcher_debug) 1.1761 + printf("jvm.cfg[%d] = ->%s<-\n", cnt, line); 1.1762 + if (vmType != VM_UNKNOWN) { 1.1763 + knownVMs[cnt].name = strdup(line); 1.1764 + knownVMs[cnt].flag = vmType; 1.1765 + switch (vmType) { 1.1766 + default: 1.1767 + break; 1.1768 + case VM_ALIASED_TO: 1.1769 + knownVMs[cnt].alias = strdup(altVMName); 1.1770 + if (_launcher_debug) { 1.1771 + printf(" name: %s vmType: %s alias: %s\n", 1.1772 + knownVMs[cnt].name, "VM_ALIASED_TO", knownVMs[cnt].alias); 1.1773 + } 1.1774 + break; 1.1775 + case VM_IF_SERVER_CLASS: 1.1776 + knownVMs[cnt].server_class = strdup(serverClassVMName); 1.1777 + if (_launcher_debug) { 1.1778 + printf(" name: %s vmType: %s server_class: %s\n", 1.1779 + knownVMs[cnt].name, "VM_IF_SERVER_CLASS", knownVMs[cnt].server_class); 1.1780 + } 1.1781 + break; 1.1782 + } 1.1783 + cnt++; 1.1784 + } 1.1785 + } 1.1786 + fclose(jvmCfg); 1.1787 + knownVMsCount = cnt; 1.1788 + 1.1789 + if (_launcher_debug) { 1.1790 + end = CounterGet(); 1.1791 + printf("%ld micro seconds to parse jvm.cfg\n", 1.1792 + (long)(jint)Counter2Micros(end-start)); 1.1793 + } 1.1794 + 1.1795 + return cnt; 1.1796 +} 1.1797 + 1.1798 + 1.1799 +static void 1.1800 +GrowKnownVMs(int minimum) 1.1801 +{ 1.1802 + struct vmdesc* newKnownVMs; 1.1803 + int newMax; 1.1804 + 1.1805 + newMax = (knownVMsLimit == 0 ? INIT_MAX_KNOWN_VMS : (2 * knownVMsLimit)); 1.1806 + if (newMax <= minimum) { 1.1807 + newMax = minimum; 1.1808 + } 1.1809 + newKnownVMs = (struct vmdesc*) MemAlloc(newMax * sizeof(struct vmdesc)); 1.1810 + if (knownVMs != NULL) { 1.1811 + memcpy(newKnownVMs, knownVMs, knownVMsLimit * sizeof(struct vmdesc)); 1.1812 + } 1.1813 + free(knownVMs); 1.1814 + knownVMs = newKnownVMs; 1.1815 + knownVMsLimit = newMax; 1.1816 +} 1.1817 + 1.1818 + 1.1819 +/* Returns index of VM or -1 if not found */ 1.1820 +static int 1.1821 +KnownVMIndex(const char* name) 1.1822 +{ 1.1823 + int i; 1.1824 + if (strncmp(name, "-J", 2) == 0) name += 2; 1.1825 + for (i = 0; i < knownVMsCount; i++) { 1.1826 + if (!strcmp(name, knownVMs[i].name)) { 1.1827 + return i; 1.1828 + } 1.1829 + } 1.1830 + return -1; 1.1831 +} 1.1832 + 1.1833 +static void 1.1834 +FreeKnownVMs() 1.1835 +{ 1.1836 + int i; 1.1837 + for (i = 0; i < knownVMsCount; i++) { 1.1838 + free(knownVMs[i].name); 1.1839 + knownVMs[i].name = NULL; 1.1840 + } 1.1841 + free(knownVMs); 1.1842 +} 1.1843 + 1.1844 +#endif /* ifndef GAMMA */