java.c revision 1892
2273N/A * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 0N/A * published by the Free Software Foundation. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1879N/A * Gamma (Hotspot internal engineering test) launcher based on 6.0u22 JDK, 1879N/A * search "GAMMA" for gamma specific changes. 1879N/A * GAMMA: gamma launcher is much simpler than regular java launcher in that 1879N/A * JVM is either statically linked in or it is installed in the 0N/A * same directory where the launcher exists, so we don't have to 0N/A * worry about choosing the right JVM based on command line flag, jar 0N/A * file and/or ergonomics. Intead of removing unused logic from source 2062N/A * they are commented out with #ifndef GAMMA, hopefully it'll be easier 0N/A * to maintain this file in sync with regular JDK launcher. 0N/A * Shared source for 'java' command line tool. 0N/A * If JAVA_ARGS is defined, then acts as a launcher for applications. For 0N/A * instance, the JDK command line tools such as javac and javadoc (see 0N/A * makefiles for more details) are built with this program. Any arguments 0N/A * prefixed with '-J' will be passed directly to the 'java' command. 0N/A * One job of the launcher is to remove command line options which the 0N/A * vm does not understand and will not process. These options include 0N/A * options which select which style of vm is run (e.g. -client and 0N/A * -server) as well as options which select the data model to use. 0N/A * Additionally, for tools which invoke an underlying vm "-J-foo" 0N/A * options are turned into "-foo" options to the vm. This option 0N/A * filtering is handled in a number of places in the launcher, some of 0N/A * it in machine-dependent code. In this file, the function 0N/A * CheckJVMType removes vm style options and TranslateApplicationArgs 0N/A * removes "-J" prefixes. On unix platforms, the 0N/A * CreateExecutionEnvironment function from the unix java_md.c file 0N/A * processes and removes -d<n> options. However, in case 0N/A * CreateExecutionEnvironment does not need to exec because 0N/A * LD_LIBRARY_PATH is set acceptably and the data model does not need 0N/A * to be changed, ParseArguments will screen out the redundant -d<n> 0N/A * options and prevent them from being passed to the vm; this is done 0N/A * by using the machine-dependent call 0N/A * RemovableMachineDependentOption. 1879N/A * The following environment variable is used to influence the behavior 1879N/A * of the jre exec'd through the SelectVersion routine. The command line * options which specify the version are not passed to the exec'd version, * because that jre may be an older version which wouldn't recognize them. * This environment variable is known to this (and later) version and serves * to suppress the version selection code. This is not only for efficiency, * but also for correctness, since any command line options have been * removed which would cause any value found in the manifest to be used. * This would be incorrect because the command line options are defined * The value associated with this environment variable is the MainClass * name from within the executable jar file (if any). This is strictly a * performance enhancement to avoid re-reading the jar file manifest. * A NOTE TO DEVELOPERS: For performance reasons it is important that * the program image remain relatively small until after SelectVersion * CreateExecutionEnvironment have finished their possibly recursive * processing. Watch everything, but resist all temptations to use Java * Entries for splash screen environment variables. * putenv is performed in SelectVersion. We need * them in memory until UnsetEnv, so they are made static * global instead of auto local. * List of VM options to be specified when the VM is created. * Prototypes for functions internal to launcher. /* Maximum supported entries from jvm.cfg. */ /* Values for vmdesc.flag */ #
endif /* ifndef GAMMA *//* flag which if set suppresses error messages from the launcher */ * Running Java code in primordial thread caused many problems. We will * create a new thread to invoke JVM. See 6316197 for more information. if (
getenv(
"_JAVA_LAUNCHER_DEBUG") != 0) {
printf(
"----_JAVA_LAUNCHER_DEBUG----\n");
* Make sure the specified version of the JRE is running. * There are three things to note about the SelectVersion() routine: * 1) If the version running isn't correct, this routine doesn't * return (either the correct version has been exec'd or an error * 2) Argc and Argv in this scope are *not* altered by this routine. * It is the responsibility of subsequent code to ignore the * arguments handled by this routine. * 3) As a side-effect, the variable "main_class" is guaranteed to * be set (if it should ever be set). This isn't exactly the * poster child for structured programming, but it is a small * price to pay for not processing a jar file operand twice. * (Note: This side effect has been disabled. See comment on #
endif /* ifndef GAMMA */ for(i = 0; i <
argc+
1; i++)
printf(
"%ld micro seconds to LoadJavaVM\n",
#
ifdef JAVA_ARGS /* javac, jar and friends. */#
else /* java, oldjava, javaw and friends */ /* Preprocess wrapper arguments */ /* Set default CLASSPATH */ if ((s =
getenv(
"CLASSPATH")) == 0) {
* Parse command line options; if the return value of * ParseArguments is false, the program should exit. /* Override class path if -jar flag was specified */ /* Set the -Dsun.java.launcher pseudo property */ /* set the -Dsun.java.launcher.* platform properties */ /* Show the splash screen if needed */ * Done with all command line processing and potential re-execs so * clean up the environment. * If user doesn't specify stack size, check if VM has a preference. * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will * return its default stack size through the init args structure. {
/* Create a new thread to create JVM and invoke main method */ * Error message to print or display; by default the message will * only be displayed in a window. char *
message =
"Fatal exception occurred. Program will exit.";
/* Initialize the virtual machine */ /* If the user specified neither a class name nor a JAR file */ printf(
"%ld micro seconds to InitializeJVM\n",
/* At this stage, argc/argv have the applications' arguments */ * Get the application's main class. * See bugid 5030265. The Main-Class name has already been parsed * from the manifest, but not parsed properly for UTF-8 support. * Hence the code here ignores the value previously extracted and * uses the pre-existing code to reextract the value. This is * possibly an end of release cycle expedient. However, it has * also been discovered that passing some character sets through * the environment has "strange" behavior on some variants of * Windows. Hence, maybe the manifest parsing code local to the * launcher should never be enhanced. * Hence, future work should either: * 1) Correct the local parsing code and verify that the * Main-Class attribute gets properly passed through * 2) Remove the vestages of maintaining main_class through * the environment (and remove these comments). const char *
format =
"Failed to load Main-Class manifest " const char *
format =
"Could not find the main class: %s. Program will exit.";
const char *
format =
"Failed to load Main Class: %s";
const char *
format =
"Could not find the main class: %s. Program will exit.";
/* Get the application's main method */ message =
"No main method found in specified class.";
{
/* Make sure the main method is public */ if(
obj ==
NULL) {
/* exception occurred */ if ((
mods &
1) == 0) {
/* if (!Modifier.isPublic(mods)) ... */ message =
"Main method not public.";
/* Build argument array */ /* Invoke main method. */ * The launcher's exit code (in the absence of calls to * System.exit) will be non-zero if main threw an exception. * Detach the main thread so that it appears to have ended when * the application's main method exits. This will invoke the * uncaught exception handler machinery if main threw an * exception. An uncaught exception handler cannot change the * launcher's return code except by calling System.exit. message =
"Could not detach main thread.";
* Wait for all non-daemon threads to end, then destroy the VM. * This will actually create a trivial new Java waiter thread * named "DestroyJavaVM", but this will be seen as a different * thread from the one that executed main, even though they are * the same C thread. This allows mainThread.join() and * mainThread.isAlive() to work as expected. * Checks the command line options to find which JVM type was * specified. If no command line option was given for the JVM type, * the default type is used. The environment variable * JDK_ALTERNATE_VM and the command line option -XXaltjvm= are also * checked as ways of specifying which JVM type to invoke. /* To make things simpler we always copy the argv array */ /* The program name is always present */ if (
arg[0] !=
'-')
break;
/* Did the user pass an explicit VM type? */ /* Did the user specify an "alternate" VM? */ * Finish copying the arguments if we aborted the above loop. * NOTE that if we aborted via "break" then we did NOT copy the * last argument above, and in addition argi will be less than /* argv is null-terminated */ /* use the default VM type if not specified (no alias processing) */ /* Use a different VM type if we are on a server class machine? */ /* if using an alternate VM, no alias processing */ /* Resolve aliases first */ fprintf(
stderr,
"Warning: %s VM not supported; %s VM will be used\n",
#
endif /* ifndef GAMMA */#
define MB (
1024UL *
KB)
#
define GB (
1024UL *
MB)
/* copied from HotSpot function "atomll()" */ while (*s !=
'\0' && *s >=
'0' && *s <=
'9') {
// 4705540: illegal if more characters are found after the first non-digit /* Create JVM with default stack and let VM handle malformed -Xss string*/ * Adds a new VM option with the given given name and value. * Expand options array if needed to accommodate at least one more * The SelectVersion() routine ensures that an appropriate version of * the JRE is running. The specification for the appropriate version * is obtained from either the manifest of a jar file (preferred) or * from command line options. * The routine also parses splash screen command line options and * passes on their values in private environment variables. * If the version has already been selected, set *main_class * with the value passed through the environment (if any) and * Scan through the arguments for options relevant to multiple JRE * support. For reference, the command line syntax is defined as: * java [options] class [argument...] * java [options] -jar file.jar [argument...] * As the scan is performed, make a copy of the argument list with * the version specification options (new to 1.5) removed, so that * a version less than 1.5 can be exec'd. * Note that due to the syntax of the native Windows interface * CreateProcess(), processing similar to the following exists in * the Windows platform specific routine ExecJRE (in java_md.c). * Changes here should be reproduced there. }
else if (
strcmp(
arg,
"-jre-restrict-search") == 0) {
}
else if (
strcmp(
arg,
"-no-jre-restrict-search") == 0) {
/* deal with "unfortunate" classpath syntax */ * Checking for headless toolkit option in the some way as AWT does: * "true" means true and any other value means false if (
argc <= 0) {
/* No operand? Possibly legit with -[full]version */ while (
argc-- > 0)
/* Copy over [argument...] */ * If there is a jar file, read the manifest. If the jarfile can't be * read, the manifest can't be read from the jar file, or the manifest * is corrupt, issue the appropriate error messages and exit. * Even if there isn't a jar file, construct a manifest_info structure * containing the command line information. It's a convenient way to carry * Command line splash screen option should have precedence * over the manifest, so the manifest data is used only if * splash_file_name has not been initialized above during command * Passing on splash screen info in environment variables * The JRE-Version and JRE-Restrict-Search values (if any) from the * manifest are overwritten by any specified on the command line. * "Valid" returns (other than unrecoverable errors) follow. Set * main_class as a side-effect of this routine. * If no version selection information is found either on the command * line or in the manifest, simply return. * Check for correct syntax of the version specification (JSR 56). * Find the appropriate JVM on the system. Just to be as forgiving as * possible, if the standard algorithms don't locate an appropriate * jre, check to see if the one running will satisfy the requirements. * This can happen on systems which haven't been set-up for multiple printf(
"JRE-Version = %s, JRE-Restrict-Search = %s Selected = %s\n",
"Unable to locate JRE meeting specification \"%s\"",
* If I'm not the chosen one, exec the chosen one. Returning from * ExecJRE indicates that I am indeed the chosen one. * The private environment variable _JAVA_VERSION_SET is used to * prevent the chosen one from re-reading the manifest file and * using the values found within to override the (potential) command * line flags stripped from argv (because the target may not * understand them). Passing the MainClass value is an optimization * to avoid locating, expanding and parsing the manifest extra #
endif /* ifndef GAMMA */ * Parses command line arguments. Returns JNI_FALSE if launcher * should exit without starting vm (e.g. certain version and usage * options); returns JNI_TRUE if vm needs to be started to process * given options. *pret (the launcher process return value) is set to }
else if (
strcmp(
arg,
"-showversion") == 0) {
* The following case provide backward compatibility with old-style }
else if (
strcmp(
arg,
"-fullversion") == 0) {
}
else if (
strcmp(
arg,
"-verifyremote") == 0) {
}
else if (
strcmp(
arg,
"-XXsuppressExitMessage") == 0) {
sprintf(
tmp,
"-Xrunhprof:cpu=old,file=%s", p +
1);
sprintf(
tmp,
"-Xrunhprof:cpu=old,file=java.prof");
}
else if (
strcmp(
arg,
"-checksource") == 0 ||
/* No longer supported */ "Warning: %s option is no longer supported.\n",
strcmp(
arg,
"-no-jre-restrict-search") == 0 ||
;
/* Ignore machine independent options already handled */ ;
/* Do not pass option to vm. */ * Initializes the Java Virtual Machine. Also frees options array when printf(
"ignoreUnrecognized is %s, ",
printf(
" option[%2d] = '%s'\n",
* Returns a new Java string object for the specified platform string. /*If the encoding specified in sun.jnu.encoding is not endorsed by "Charset.isSupported" we have to fall back to use String(byte[]) explicitly here without specifying the encoding name, in which the StringCoding class will pickup the iso-8859-1 as the fallback converter for us. * Returns a new array of Java string objects for the specified * array of platform strings. for (i = 0; i <
strc; i++) {
* Loads a class, convert the '.' to '/'. *s++ = (c ==
'.') ?
'/' : c;
printf(
"%ld micro seconds to load main class\n",
printf(
"----_JAVA_LAUNCHER_DEBUG----\n");
* Returns the main class name for the specified jar file. * For tools, convert command line args thus: * javac -cp foo:foo/"*" -J-ms32m ... * java -ms32m -cp JLI_WildcardExpandClasspath(foo:foo/"*") ... /* Copy the VM arguments (i.e. prefixed with -J) */ if (
arg[0] ==
'-' &&
arg[
1] ==
'J') {
for (i = 0; i <
argc; i++) {
if (
arg[0] ==
'-' &&
arg[
1] ==
'J') {
/* Copy the rest of the arguments */ if (
arg[0] !=
'-' ||
arg[
1] !=
'J') {
for (i = 0; i <
argc; i++) {
* For our tools, we try to add 3 VM options: * <envcp> is the user's setting of CLASSPATH -- for instance the user * tells javac where to find binary classes through this environment * variable. Notice that users will be able to compile against our * tools.jar to CLASSPATH. * <apphome> is the directory where the application is installed. * <appcp> is the classpath to where our apps' classfiles are. const char *s =
getenv(
"CLASSPATH");
/* 40 for -Denv.class.path= */ /* How big is the application's classpath? */ * inject the -Dsun.java.command pseudo property into the args structure * this pseudo property is used in the HotSpot VM to expose the * Java class name and arguments to the main method to the VM. The * HotSpot VM uses this pseudo property to store the Java class name * (or jar file name) and the arguments to the class's main method * to the instrumentation memory region. The sun.java.command pseudo * property is not exported by HotSpot to the Java layer. /* unexpected, one of these should be set. just return without /* if the class name is not set, then use the jarfile name */ /* determine the amount of memory to allocate assuming * the individual components will be space separated for (i = 0; i <
argc; i++) {
/* allocate the memory */ /* build the -D string */ for (i = 0; i <
argc; i++) {
/* the components of the string are space separated. In * the case of embedded white space, the relationship of * the white space separated components to their true * positional arguments will be ambiguous. This issue may * be addressed in a future release. * JVM would like to know if it's created by a standard Sun launcher, or by * user native application, the following property indicates the former. * Prints the version information from the java.version and other properties. * Prints default usage message. "Usage: %s [-options] class [args...]\n" " (to execute a class)\n" " or %s [-options] -jar jarfile [args...]\n" " (to execute a jar file)\n" "where options include:\n",
"the \"%s\" VM [deprecated]\n",
/* The first known VM is the default */ reason =
"because you are running on a server-class machine.\n";
#
endif /* ifndef GAMMA */" -cp <class search path of directories and zip/jar files>\n" " -classpath <class search path of directories and zip/jar files>\n" " A %c separated list of directories, JAR archives,\n" " and ZIP archives to search for class files.\n" " set a system property\n" " -verbose[:class|gc|jni]\n" " enable verbose output\n" " -version print product version and exit\n" " require the specified version to run\n" " -showversion print product version and continue\n" " -jre-restrict-search | -jre-no-restrict-search\n" " -? -help print this help message\n" " -X print help on non-standard options\n" " -ea[:<packagename>...|:<classname>]\n" " -enableassertions[:<packagename>...|:<classname>]\n" " -da[:<packagename>...|:<classname>]\n" " -disableassertions[:<packagename>...|:<classname>]\n" " -esa | -enablesystemassertions\n" " enable system assertions\n" " -dsa | -disablesystemassertions\n" " disable system assertions\n" " -agentlib:<libname>[=<options>]\n" " load native agent library <libname>, e.g. -agentlib:hprof\n" " see also, -agentlib:jdwp=help and -agentlib:hprof=help\n" " -agentpath:<pathname>[=<options>]\n" " load native agent library by full pathname\n" " -javaagent:<jarpath>[=<options>]\n" " load Java programming language agent, see java.lang.instrument\n" " show splash screen with specified image\n" * Print usage message for -X options. A 32 bit cushion to prevent buffer overrun, noting that fopen(3C) may fail if the buffer exceeds MAXPATHLEN. /* Note the FILE_SEPARATOR is platform dependent */ * Read the jvm.cfg file and fill the knownJVMs[] array. * The functionality of the jvm.cfg file is subject to change without * notice and the mechanism will be removed in the future. * The lexical structure of the jvm.cfg file is as follows: * knownLine := flag "KNOWN" EOL * warnLine := flag "WARN" EOL * ignoreLine := flag "IGNORE" EOL * errorLine := flag "ERROR" EOL * aliasLine := flag "ALIASED_TO" flag EOL * predicateLine := flag "IF_SERVER_CLASS" flag EOL * commentLine := "#" text EOL * The semantics are that when someone specifies a flag on the command line: * - if the flag appears on a knownLine, then the identifier is used as * the name of the directory holding the JVM library (the name of the JVM). * - if the flag appears as the first flag on an aliasLine, the identifier * of the second flag is used as the name of the JVM. * - if the flag appears on a warnLine, the identifier is used as the * name of the JVM, but a warning is generated. * - if the flag appears on an ignoreLine, the identifier is recognized as the * name of a JVM, but the identifier is ignored and the default vm used * - if the flag appears on an errorLine, an error is generated. * - if the flag appears as the first flag on a predicateLine, and * the machine on which you are running passes the predicate indicated, * then the identifier of the second flag is used as the name of the JVM, * otherwise the identifier of the first flag is used as the name of the JVM. * If no flag is given on the command line, the first vmLine of the jvm.cfg * file determines the name of the JVM. * PredicateLines are only interpreted on first vmLine of a jvm.cfg file, * since they only make sense if someone hasn't specified the name of the * JVM on the command line. * The intent of the jvm.cfg file is to allow several JVM libraries to * be installed in different subdirectories of a single JRE installation, * for space-savings and convenience in testing. * The intent is explicitly not to provide a full aliasing or predicate /* Null-terminate this string for JLI_StringDup below */ fprintf(
stderr,
"Warning: missing VM alias on line %d of `%s'\n",
/* Null terminate altVMName */ fprintf(
stderr,
"Warning: missing server class VM on line %d of `%s'\n",
/* Null terminate server class VM name */ printf(
" name: %s vmType: %s alias: %s\n",
printf(
" name: %s vmType: %s server_class: %s\n",
/* Returns index of VM or -1 if not found */ * Displays the splash screen according to the jar file name * and image file names stored in environment variables #
endif /* ifndef GAMMA */