6981484: Update development launcher
authorsla
Thu, 02 Dec 2010 05:45:54 -0800
changeset 7410 f5b282e7a7a6
parent 7409 e9017b2bef9c
child 7411 afcfb75ccae1
6981484: Update development launcher Summary: Add new development launcher called hotspot(.exe) Reviewed-by: coleenp
hotspot/make/linux/makefiles/launcher.make
hotspot/make/solaris/makefiles/launcher.make
hotspot/make/windows/makefiles/debug.make
hotspot/make/windows/makefiles/fastdebug.make
hotspot/make/windows/makefiles/launcher.make
hotspot/make/windows/makefiles/product.make
hotspot/src/os/linux/launcher/java.c
hotspot/src/os/linux/launcher/java.h
hotspot/src/os/linux/launcher/java_md.c
hotspot/src/os/linux/launcher/java_md.h
hotspot/src/os/posix/launcher/java_md.c
hotspot/src/os/posix/launcher/java_md.h
hotspot/src/os/posix/launcher/launcher.script
hotspot/src/os/solaris/launcher/java.c
hotspot/src/os/solaris/launcher/java.h
hotspot/src/os/solaris/launcher/java_md.c
hotspot/src/os/solaris/launcher/java_md.h
hotspot/src/os/windows/launcher/java_md.c
hotspot/src/os/windows/launcher/java_md.h
hotspot/src/os/windows/vm/os_windows.cpp
hotspot/src/share/tools/launcher/java.c
hotspot/src/share/tools/launcher/java.h
hotspot/src/share/tools/launcher/jli_util.c
hotspot/src/share/tools/launcher/jli_util.h
hotspot/src/share/tools/launcher/wildcard.c
hotspot/src/share/tools/launcher/wildcard.h
hotspot/src/share/vm/prims/jvm.h
--- a/hotspot/make/linux/makefiles/launcher.make	Thu Dec 02 20:01:47 2010 +0100
+++ b/hotspot/make/linux/makefiles/launcher.make	Thu Dec 02 05:45:54 2010 -0800
@@ -24,19 +24,23 @@
 
 # Rules to build gamma launcher, used by vm.make
 
-# gamma[_g]: launcher
 
+LAUNCHER_SCRIPT = hotspot
 LAUNCHER   = gamma
-LAUNCHER_G = $(LAUNCHER)$(G_SUFFIX)
 
-LAUNCHERDIR   = $(GAMMADIR)/src/os/$(Platform_os_family)/launcher
-LAUNCHERFLAGS = $(ARCHFLAG) \
+LAUNCHERDIR   := $(GAMMADIR)/src/os/posix/launcher
+LAUNCHERDIR_SHARE := $(GAMMADIR)/src/share/tools/launcher
+LAUNCHERFLAGS := $(ARCHFLAG) \
                 -I$(LAUNCHERDIR) -I$(GAMMADIR)/src/share/vm/prims \
+                -I$(LAUNCHERDIR_SHARE) \
                 -DFULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \
+                -DJDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \
+                -DJDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \
                 -DARCH=\"$(LIBARCH)\" \
                 -DGAMMA \
                 -DLAUNCHER_TYPE=\"gamma\" \
-                -DLINK_INTO_$(LINK_INTO)
+                -DLINK_INTO_$(LINK_INTO) \
+                $(TARGET_DEFINES)
 
 ifeq ($(LINK_INTO),AOUT)
   LAUNCHER.o                 = launcher.o $(JVM_OBJ_FILES)
@@ -55,22 +59,35 @@
 LINK_LAUNCHER/PRE_HOOK  = $(LINK_LIB.CC/PRE_HOOK)
 LINK_LAUNCHER/POST_HOOK = $(LINK_LIB.CC/POST_HOOK)
 
-launcher.o: launcher.c $(LAUNCHERDIR)/java.c $(LAUNCHERDIR)/java_md.c
-	$(CC) -g -c -o $@ launcher.c $(LAUNCHERFLAGS) $(CPPFLAGS) $(TARGET_DEFINES)
+LAUNCHER_OUT = launcher
+
+SUFFIXES += .d
+
+SOURCES := $(shell find $(LAUNCHERDIR) -name "*.c")
+SOURCES_SHARE := $(shell find $(LAUNCHERDIR_SHARE) -name "*.c")
+
+OBJS := $(patsubst $(LAUNCHERDIR)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES)) $(patsubst $(LAUNCHERDIR_SHARE)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES_SHARE))
+
+DEPFILES := $(patsubst %.o,%.d,$(OBJS))
+-include $(DEPFILES)
+
+$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR_SHARE)/%.c
+	$(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); }
+	$(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS)
 
-launcher.c:
-	@echo Generating $@
-	$(QUIETLY) { \
-	echo '#define debug launcher_debug'; \
-	echo '#include "java.c"'; \
-	echo '#include "java_md.c"'; \
-	} > $@
+$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c
+	$(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); }
+	$(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS)
 
-$(LAUNCHER): $(LAUNCHER.o) $(LIBJVM) $(LAUNCHER_MAPFILE)
-	$(QUIETLY) { \
-	    echo Linking launcher...; \
-	    $(LINK_LAUNCHER/PRE_HOOK) \
-	    $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(LAUNCHER.o) $(LIBS_LAUNCHER); \
-	    $(LINK_LAUNCHER/POST_HOOK) \
-	    [ -f $(LAUNCHER_G) ] || { ln -s $@ $(LAUNCHER_G); }; \
-        }
+$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE)
+	$(QUIETLY) echo Linking launcher...
+	$(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK)
+	$(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(OBJS) $(LIBS_LAUNCHER)
+	$(QUIETLY) $(LINK_LAUNCHER/POST_HOOK)
+
+$(LAUNCHER): $(LAUNCHER_SCRIPT)
+
+$(LAUNCHER_SCRIPT): $(LAUNCHERDIR)/launcher.script
+	$(QUIETLY) sed -e 's/@@LIBARCH@@/$(LIBARCH)/g' $< > $@
+	$(QUIETLY) chmod +x $@
+
--- a/hotspot/make/solaris/makefiles/launcher.make	Thu Dec 02 20:01:47 2010 +0100
+++ b/hotspot/make/solaris/makefiles/launcher.make	Thu Dec 02 05:45:54 2010 -0800
@@ -24,18 +24,22 @@
 
 # Rules to build gamma launcher, used by vm.make
 
-# gamma[_g]: launcher
+LAUNCHER_SCRIPT = hotspot
 LAUNCHER   = gamma
-LAUNCHER_G = $(LAUNCHER)$(G_SUFFIX)
 
-LAUNCHERDIR   = $(GAMMADIR)/src/os/$(Platform_os_family)/launcher
+LAUNCHERDIR   = $(GAMMADIR)/src/os/posix/launcher
+LAUNCHERDIR_SHARE := $(GAMMADIR)/src/share/tools/launcher
 LAUNCHERFLAGS = $(ARCHFLAG) \
                 -I$(LAUNCHERDIR) -I$(GAMMADIR)/src/share/vm/prims \
+                -I$(LAUNCHERDIR_SHARE) \
                 -DFULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \
+                -DJDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \
+                -DJDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \
                 -DARCH=\"$(LIBARCH)\" \
                 -DGAMMA \
                 -DLAUNCHER_TYPE=\"gamma\" \
-                -DLINK_INTO_$(LINK_INTO)
+                -DLINK_INTO_$(LINK_INTO) \
+                $(TARGET_DEFINES)
 
 ifeq ($(LINK_INTO),AOUT)
   LAUNCHER.o                 = launcher.o $(JVM_OBJ_FILES)
@@ -68,24 +72,37 @@
 #LAUNCHERFLAGS += -W0,-noglobal
 endif # Platform_compiler == sparcWorks
 
-launcher.o: launcher.c $(LAUNCHERDIR)/java.c $(LAUNCHERDIR)/java_md.c
-	$(CC) -g -c -o $@ launcher.c $(LAUNCHERFLAGS) $(CPPFLAGS) ${TARGET_DEFINES}
+LAUNCHER_OUT = launcher
+
+SUFFIXES += .d
+
+SOURCES := $(shell find $(LAUNCHERDIR) -name "*.c")
+SOURCES_SHARE := $(shell find $(LAUNCHERDIR_SHARE) -name "*.c")
+
+OBJS := $(patsubst $(LAUNCHERDIR)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES)) $(patsubst $(LAUNCHERDIR_SHARE)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES_SHARE))
+
+DEPFILES := $(patsubst %.o,%.d,$(OBJS))
+-include $(DEPFILES)
 
-launcher.c:
-	@echo Generating $@
-	$(QUIETLY) { \
-	echo '#define debug launcher_debug'; \
-	echo '#include "java.c"'; \
-	echo '#include "java_md.c"'; \
-	} > $@
+$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR_SHARE)/%.c
+	$(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); }
+	$(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS)
 
-$(LAUNCHER): $(LAUNCHER.o) $(LIBJVM) $(LAUNCHER_MAPFILE)
+$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c
+	$(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); }
+	$(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS)
+
+$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE)
 ifeq ($(filter -sbfast -xsbfast, $(CFLAGS_BROWSE)),)
-	@echo Linking launcher...
+	$(QUIETLY) echo Linking launcher...
 	$(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK)
-	$(QUIETLY) \
-	$(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(LAUNCHER.o) $(LIBS_LAUNCHER)
+	$(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(OBJS) $(LIBS_LAUNCHER)
 	$(QUIETLY) $(LINK_LAUNCHER/POST_HOOK)
-	[ -f $(LAUNCHER_G) ] || ln -s $@ $(LAUNCHER_G)
 endif # filter -sbfast -xsbfast
 
+$(LAUNCHER): $(LAUNCHER_SCRIPT)
+
+$(LAUNCHER_SCRIPT): $(LAUNCHERDIR)/launcher.script
+	$(QUIETLY) sed -e 's/@@LIBARCH@@/$(LIBARCH)/g' $< > $@
+	$(QUIETLY) chmod +x $@
+
--- a/hotspot/make/windows/makefiles/debug.make	Thu Dec 02 20:01:47 2010 +0100
+++ b/hotspot/make/windows/makefiles/debug.make	Thu Dec 02 05:45:54 2010 -0800
@@ -26,6 +26,7 @@
 HS_FNAME=$(HS_INTERNAL_NAME).dll
 AOUT=$(HS_FNAME)
 SAWINDBG=sawindbg.dll
+LAUNCHER_NAME=hotspot.exe
 GENERATED=../generated
 
 # Allow the user to turn off precompiled headers from the command line.
@@ -33,7 +34,7 @@
 BUILD_PCH_FILE=_build_pch_file.obj
 !endif
 
-default:: $(BUILD_PCH_FILE) $(AOUT) checkAndBuildSA
+default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA
 
 !include ../local.make
 !include compile.make
@@ -62,3 +63,4 @@
 
 !include $(WorkSpace)/make/windows/makefiles/shared.make
 !include $(WorkSpace)/make/windows/makefiles/sa.make
+!include $(WorkSpace)/make/windows/makefiles/launcher.make
--- a/hotspot/make/windows/makefiles/fastdebug.make	Thu Dec 02 20:01:47 2010 +0100
+++ b/hotspot/make/windows/makefiles/fastdebug.make	Thu Dec 02 05:45:54 2010 -0800
@@ -26,6 +26,7 @@
 HS_FNAME=$(HS_INTERNAL_NAME).dll
 AOUT=$(HS_FNAME)
 SAWINDBG=sawindbg.dll
+LAUNCHER_NAME=hotspot.exe
 GENERATED=../generated
 
 # Allow the user to turn off precompiled headers from the command line.
@@ -33,7 +34,7 @@
 BUILD_PCH_FILE=_build_pch_file.obj
 !endif
 
-default:: $(BUILD_PCH_FILE) $(AOUT) checkAndBuildSA
+default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA
 
 !include ../local.make
 !include compile.make
@@ -62,3 +63,4 @@
 
 !include $(WorkSpace)/make/windows/makefiles/shared.make
 !include $(WorkSpace)/make/windows/makefiles/sa.make
+!include $(WorkSpace)/make/windows/makefiles/launcher.make
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/make/windows/makefiles/launcher.make	Thu Dec 02 05:45:54 2010 -0800
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#  
+#
+
+LAUNCHER_FLAGS=$(ARCHFLAG) \
+	/D FULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \
+	/D JDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \
+	/D JDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \
+	/D GAMMA \
+	/D LAUNCHER_TYPE=\"gamma\" \
+	/D _CRT_SECURE_NO_WARNINGS \
+	/D _CRT_SECURE_NO_DEPRECATE \
+	/D LINK_INTO_LIBJVM \
+	/I $(WorkSpace)\src\os\windows\launcher \
+	/I $(WorkSpace)\src\share\tools\launcher
+
+CPP_FLAGS=$(CPP_FLAGS) $(LAUNCHER_FLAGS)
+
+LINK_FLAGS=/manifest $(HS_INTERNAL_NAME).lib kernel32.lib user32.lib /nologo /machine:$(MACHINE) /map /debug /subsystem:console 
+
+!if "$(COMPILER_NAME)" == "VS2005"
+# This VS2005 compiler has /GS as a default and requires bufferoverflowU.lib
+#    on the link command line, otherwise we get missing __security_check_cookie
+#    externals at link time. Even with /GS-, you need bufferoverflowU.lib.
+BUFFEROVERFLOWLIB = bufferoverflowU.lib
+LINK_FLAGS = $(LINK_FLAGS) $(BUFFEROVERFLOWLIB)
+!endif
+
+LAUNCHERDIR = $(GAMMADIR)/src/os/windows/launcher
+LAUNCHERDIR_SHARE = $(GAMMADIR)/src/share/tools/launcher
+
+OUTDIR = launcher
+
+{$(LAUNCHERDIR)}.c{$(OUTDIR)}.obj:
+	-mkdir $(OUTDIR)
+        $(CPP) $(CPP_FLAGS) /c /Fo$@ $<
+
+{$(LAUNCHERDIR_SHARE)}.c{$(OUTDIR)}.obj:
+	-mkdir $(OUTDIR)
+        $(CPP) $(CPP_FLAGS) /c /Fo$@ $<
+
+$(OUTDIR)\*.obj: $(LAUNCHERDIR)\*.c $(LAUNCHERDIR)\*.h $(LAUNCHERDIR_SHARE)\*.c $(LAUNCHERDIR_SHARE)\*.h
+
+$(LAUNCHER_NAME): $(OUTDIR)\java.obj $(OUTDIR)\java_md.obj $(OUTDIR)\jli_util.obj
+	$(LINK) $(LINK_FLAGS) /out:$@ $**
+
+
--- a/hotspot/make/windows/makefiles/product.make	Thu Dec 02 20:01:47 2010 +0100
+++ b/hotspot/make/windows/makefiles/product.make	Thu Dec 02 05:45:54 2010 -0800
@@ -25,6 +25,7 @@
 HS_INTERNAL_NAME=jvm
 HS_FNAME=$(HS_INTERNAL_NAME).dll
 AOUT=$(HS_FNAME)
+LAUNCHER_NAME=hotspot.exe
 GENERATED=../generated
 
 # Allow the user to turn off precompiled headers from the command line.
@@ -32,7 +33,7 @@
 BUILD_PCH_FILE=_build_pch_file.obj
 !endif
 
-default:: $(BUILD_PCH_FILE) $(AOUT) checkAndBuildSA
+default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA
 
 !include ../local.make
 !include compile.make
@@ -73,3 +74,4 @@
 
 !include $(WorkSpace)/make/windows/makefiles/shared.make
 !include $(WorkSpace)/make/windows/makefiles/sa.make
+!include $(WorkSpace)/make/windows/makefiles/launcher.make
--- a/hotspot/src/os/linux/launcher/java.c	Thu Dec 02 20:01:47 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1842 +0,0 @@
-/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK,
- * search "GAMMA" for gamma specific changes.
- *
- * GAMMA: gamma launcher is much simpler than regular java launcher in that
- *        JVM is either statically linked in or it is installed in the
- *        same directory where the launcher exists, so we don't have to
- *        worry about choosing the right JVM based on command line flag, jar
- *        file and/or ergonomics. Intead of removing unused logic from source
- *        they are commented out with #ifndef GAMMA, hopefully it'll be easier
- *        to maintain this file in sync with regular JDK launcher.
- */
-
-/*
- * Shared source for 'java' command line tool.
- *
- * If JAVA_ARGS is defined, then acts as a launcher for applications. For
- * instance, the JDK command line tools such as javac and javadoc (see
- * makefiles for more details) are built with this program.  Any arguments
- * prefixed with '-J' will be passed directly to the 'java' command.
- */
-
-#ifdef GAMMA
-#  ifdef JAVA_ARGS
-#    error Do NOT define JAVA_ARGS when building gamma launcher
-#  endif
-#  if !defined(LINK_INTO_AOUT) && !defined(LINK_INTO_LIBJVM)
-#    error Either LINK_INTO_AOUT or LINK_INTO_LIBJVM must be defined
-#  endif
-#endif
-
-/*
- * One job of the launcher is to remove command line options which the
- * vm does not understand and will not process.  These options include
- * options which select which style of vm is run (e.g. -client and
- * -server) as well as options which select the data model to use.
- * Additionally, for tools which invoke an underlying vm "-J-foo"
- * options are turned into "-foo" options to the vm.  This option
- * filtering is handled in a number of places in the launcher, some of
- * it in machine-dependent code.  In this file, the function
- * CheckJVMType removes vm style options and TranslateDashJArgs
- * removes "-J" prefixes.  On unix platforms, the
- * CreateExecutionEnvironment function from the unix java_md.c file
- * processes and removes -d<n> options.  However, in case
- * CreateExecutionEnvironment does not need to exec because
- * LD_LIBRARY_PATH is set acceptably and the data model does not need
- * to be changed, ParseArguments will screen out the redundant -d<n>
- * options and prevent them from being passed to the vm; this is done
- * by using the machine-dependent call
- * RemovableMachineDependentOption.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jni.h>
-#include "java.h"
-
-#ifndef GAMMA
-#include "manifest_info.h"
-#include "version_comp.h"
-#endif
-
-#ifndef FULL_VERSION
-#define FULL_VERSION JDK_MAJOR_VERSION "." JDK_MINOR_VERSION
-#endif
-
-/*
- * The following environment variable is used to influence the behavior
- * 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
- * to take precedence.
- *
- * 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
- * interfaces.
- */
-#define ENV_ENTRY "_JAVA_VERSION_SET"
-
-static jboolean printVersion = JNI_FALSE; /* print and exit */
-static jboolean showVersion = JNI_FALSE;  /* print but continue */
-static char *progname;
-jboolean _launcher_debug = JNI_FALSE;
-
-/*
- * List of VM options to be specified when the VM is created.
- */
-static JavaVMOption *options;
-static int numOptions, maxOptions;
-
-/*
- * Prototypes for functions internal to launcher.
- */
-static void AddOption(char *str, void *info);
-static void SetClassPath(char *s);
-static void SelectVersion(int argc, char **argv, char **main_class);
-static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile,
-                               char **pclassname, int *pret);
-static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
-                              InvocationFunctions *ifn);
-static jstring NewPlatformString(JNIEnv *env, char *s);
-static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc);
-static jclass LoadClass(JNIEnv *env, char *name);
-static jstring GetMainClassName(JNIEnv *env, char *jarname);
-static void SetJavaCommandLineProp(char* classname, char* jarfile, int argc, char** argv);
-#ifdef GAMMA
-static void SetJavaLauncherProp(void);
-#endif
-
-#ifdef JAVA_ARGS
-static void TranslateDashJArgs(int *pargc, char ***pargv);
-static jboolean AddApplicationOptions(void);
-#endif
-
-static void PrintJavaVersion(JNIEnv *env);
-static void PrintUsage(void);
-static jint PrintXUsage(void);
-
-static void SetPaths(int argc, char **argv);
-
-/* Maximum supported entries from jvm.cfg. */
-#define INIT_MAX_KNOWN_VMS      10
-/* Values for vmdesc.flag */
-#define VM_UNKNOWN              -1
-#define VM_KNOWN                 0
-#define VM_ALIASED_TO            1
-#define VM_WARN                  2
-#define VM_ERROR                 3
-#define VM_IF_SERVER_CLASS       4
-#define VM_IGNORE                5
-struct vmdesc {
-    char *name;
-    int flag;
-    char *alias;
-    char *server_class;
-};
-static struct vmdesc *knownVMs = NULL;
-static int knownVMsCount = 0;
-static int knownVMsLimit = 0;
-
-static void GrowKnownVMs();
-static int  KnownVMIndex(const char* name);
-static void FreeKnownVMs();
-
-jboolean ServerClassMachine();
-
-/* flag which if set suppresses error messages from the launcher */
-static int noExitErrorMessage = 0;
-
-/*
- * Entry point.
- */
-int
-main(int argc, char ** argv)
-{
-    JavaVM *vm = 0;
-    JNIEnv *env = 0;
-    char *jarfile = 0;
-    char *classname = 0;
-    char *s = 0;
-    char *main_class = NULL;
-    jstring mainClassName;
-    jclass mainClass;
-    jmethodID mainID;
-    jobjectArray mainArgs;
-    int ret;
-    InvocationFunctions ifn;
-    jlong start, end;
-    char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN];
-    char ** original_argv = argv;
-
-    /*
-     * 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.";
-    jboolean messageDest = JNI_FALSE;
-
-    if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) {
-        _launcher_debug = JNI_TRUE;
-        printf("----_JAVA_LAUNCHER_DEBUG----\n");
-    }
-
-#ifndef GAMMA
-    /*
-     * 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
-     *     was issued).
-     *  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
-     *     bugid 5030265 below.)
-     */
-    SelectVersion(argc, argv, &main_class);
-#endif /* ifndef GAMMA */
-
-    /* copy original argv */
-    {
-      int i;
-      original_argv = (char**)MemAlloc(sizeof(char*)*(argc+1));
-      for(i = 0; i < argc+1; i++)
-        original_argv[i] = argv[i];
-    }
-
-    CreateExecutionEnvironment(&argc, &argv,
-                               jrepath, sizeof(jrepath),
-                               jvmpath, sizeof(jvmpath),
-                               original_argv);
-    ifn.CreateJavaVM = 0;
-    ifn.GetDefaultJavaVMInitArgs = 0;
-
-    if (_launcher_debug)
-      start = CounterGet();
-    if (!LoadJavaVM(jvmpath, &ifn)) {
-      exit(6);
-    }
-    if (_launcher_debug) {
-      end   = CounterGet();
-      printf("%ld micro seconds to LoadJavaVM\n",
-             (long)(jint)Counter2Micros(end-start));
-    }
-
-#ifdef JAVA_ARGS  /* javac, jar and friends. */
-    progname = "java";
-#else             /* java, oldjava, javaw and friends */
-#ifdef PROGNAME
-    progname = PROGNAME;
-#else
-    progname = *argv;
-    if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) {
-        progname = s + 1;
-    }
-#endif /* PROGNAME */
-#endif /* JAVA_ARGS */
-    ++argv;
-    --argc;
-
-#ifdef JAVA_ARGS
-    /* Preprocess wrapper arguments */
-    TranslateDashJArgs(&argc, &argv);
-    if (!AddApplicationOptions()) {
-        exit(1);
-    }
-#endif
-
-    /* Set default CLASSPATH */
-    if ((s = getenv("CLASSPATH")) == 0) {
-        s = ".";
-    }
-#ifndef JAVA_ARGS
-    SetClassPath(s);
-#endif
-
-    /*
-     *  Parse command line options; if the return value of
-     *  ParseArguments is false, the program should exit.
-     */
-    if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret)) {
-      exit(ret);
-    }
-
-    /* Override class path if -jar flag was specified */
-    if (jarfile != 0) {
-        SetClassPath(jarfile);
-    }
-
-    /* set the -Dsun.java.command pseudo property */
-    SetJavaCommandLineProp(classname, jarfile, argc, argv);
-
-#ifdef GAMMA
-    /* Set the -Dsun.java.launcher pseudo property */
-    SetJavaLauncherProp();
-#endif
-
-    /*
-     * Done with all command line processing and potential re-execs so
-     * clean up the environment.
-     */
-    (void)UnsetEnv(ENV_ENTRY);
-
-    /* Initialize the virtual machine */
-
-    if (_launcher_debug)
-        start = CounterGet();
-    if (!InitializeJVM(&vm, &env, &ifn)) {
-        ReportErrorMessage("Could not create the Java virtual machine.",
-                           JNI_TRUE);
-        exit(1);
-    }
-
-    if (printVersion || showVersion) {
-        PrintJavaVersion(env);
-        if ((*env)->ExceptionOccurred(env)) {
-            ReportExceptionDescription(env);
-            goto leave;
-        }
-        if (printVersion) {
-            ret = 0;
-            message = NULL;
-            goto leave;
-        }
-        if (showVersion) {
-            fprintf(stderr, "\n");
-        }
-    }
-
-    /* If the user specified neither a class name nor a JAR file */
-    if (jarfile == 0 && classname == 0) {
-        PrintUsage();
-        message = NULL;
-        goto leave;
-    }
-
-#ifndef GAMMA
-    FreeKnownVMs();  /* after last possible PrintUsage() */
-#endif
-
-    if (_launcher_debug) {
-        end   = CounterGet();
-        printf("%ld micro seconds to InitializeJVM\n",
-               (long)(jint)Counter2Micros(end-start));
-    }
-
-    /* At this stage, argc/argv have the applications' arguments */
-    if (_launcher_debug) {
-        int i = 0;
-        printf("Main-Class is '%s'\n", classname ? classname : "");
-        printf("Apps' argc is %d\n", argc);
-        for (; i < argc; i++) {
-            printf("    argv[%2d] = '%s'\n", i, argv[i]);
-        }
-    }
-
-    ret = 1;
-
-    /*
-     * 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
-     *          all environments,
-     *     2)   Remove the vestages of maintaining main_class through
-     *          the environment (and remove these comments).
-     */
-    if (jarfile != 0) {
-        mainClassName = GetMainClassName(env, jarfile);
-        if ((*env)->ExceptionOccurred(env)) {
-            ReportExceptionDescription(env);
-            goto leave;
-        }
-        if (mainClassName == NULL) {
-          const char * format = "Failed to load Main-Class manifest "
-                                "attribute from\n%s";
-          message = (char*)MemAlloc((strlen(format) + strlen(jarfile)) *
-                                    sizeof(char));
-          sprintf(message, format, jarfile);
-          messageDest = JNI_TRUE;
-          goto leave;
-        }
-        classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
-        if (classname == NULL) {
-            ReportExceptionDescription(env);
-            goto leave;
-        }
-        mainClass = LoadClass(env, classname);
-        if(mainClass == NULL) { /* exception occurred */
-            ReportExceptionDescription(env);
-            message = "Could not find the main class.  Program will exit.";
-            goto leave;
-        }
-        (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
-    } else {
-      mainClassName = NewPlatformString(env, classname);
-      if (mainClassName == NULL) {
-        const char * format = "Failed to load Main Class: %s";
-        message = (char *)MemAlloc((strlen(format) + strlen(classname)) *
-                                   sizeof(char) );
-        sprintf(message, format, classname);
-        messageDest = JNI_TRUE;
-        goto leave;
-      }
-      classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
-      if (classname == NULL) {
-        ReportExceptionDescription(env);
-        goto leave;
-      }
-      mainClass = LoadClass(env, classname);
-      if(mainClass == NULL) { /* exception occurred */
-        ReportExceptionDescription(env);
-        message = "Could not find the main class. Program will exit.";
-        goto leave;
-      }
-      (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
-    }
-
-    /* Get the application's main method */
-    mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
-                                       "([Ljava/lang/String;)V");
-    if (mainID == NULL) {
-        if ((*env)->ExceptionOccurred(env)) {
-            ReportExceptionDescription(env);
-        } else {
-          message = "No main method found in specified class.";
-          messageDest = JNI_TRUE;
-        }
-        goto leave;
-    }
-
-    {    /* Make sure the main method is public */
-        jint mods;
-        jmethodID mid;
-        jobject obj = (*env)->ToReflectedMethod(env, mainClass,
-                                                mainID, JNI_TRUE);
-
-        if( obj == NULL) { /* exception occurred */
-            ReportExceptionDescription(env);
-            goto leave;
-        }
-
-        mid =
-          (*env)->GetMethodID(env,
-                              (*env)->GetObjectClass(env, obj),
-                              "getModifiers", "()I");
-        if ((*env)->ExceptionOccurred(env)) {
-            ReportExceptionDescription(env);
-            goto leave;
-        }
-
-        mods = (*env)->CallIntMethod(env, obj, mid);
-        if ((mods & 1) == 0) { /* if (!Modifier.isPublic(mods)) ... */
-            message = "Main method not public.";
-            messageDest = JNI_TRUE;
-            goto leave;
-        }
-    }
-
-    /* Build argument array */
-    mainArgs = NewPlatformStringArray(env, argv, argc);
-    if (mainArgs == NULL) {
-        ReportExceptionDescription(env);
-        goto leave;
-    }
-
-    /* Invoke main method. */
-    (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
-
-    /*
-     * The launcher's exit code (in the absence of calls to
-     * System.exit) will be non-zero if main threw an exception.
-     */
-    ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
-
-    /*
-     * 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.
-     */
-    if ((*vm)->DetachCurrentThread(vm) != 0) {
-        message = "Could not detach main thread.";
-        messageDest = JNI_TRUE;
-        ret = 1;
-        goto leave;
-    }
-
-    message = NULL;
-
- leave:
-    /*
-     * 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.
-     */
-    (*vm)->DestroyJavaVM(vm);
-
-    if(message != NULL && !noExitErrorMessage)
-      ReportErrorMessage(message, messageDest);
-    return ret;
-}
-
-
-#ifndef GAMMA
-/*
- * 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.
- */
-char *
-CheckJvmType(int *pargc, char ***argv, jboolean speculative) {
-    int i, argi;
-    int argc;
-    char **newArgv;
-    int newArgvIdx = 0;
-    int isVMType;
-    int jvmidx = -1;
-    char *jvmtype = getenv("JDK_ALTERNATE_VM");
-
-    argc = *pargc;
-
-    /* To make things simpler we always copy the argv array */
-    newArgv = MemAlloc((argc + 1) * sizeof(char *));
-
-    /* The program name is always present */
-    newArgv[newArgvIdx++] = (*argv)[0];
-
-    for (argi = 1; argi < argc; argi++) {
-        char *arg = (*argv)[argi];
-        isVMType = 0;
-
-#ifdef JAVA_ARGS
-        if (arg[0] != '-') {
-            newArgv[newArgvIdx++] = arg;
-            continue;
-        }
-#else
-        if (strcmp(arg, "-classpath") == 0 ||
-            strcmp(arg, "-cp") == 0) {
-            newArgv[newArgvIdx++] = arg;
-            argi++;
-            if (argi < argc) {
-                newArgv[newArgvIdx++] = (*argv)[argi];
-            }
-            continue;
-        }
-        if (arg[0] != '-') break;
-#endif
-
-        /* Did the user pass an explicit VM type? */
-        i = KnownVMIndex(arg);
-        if (i >= 0) {
-            jvmtype = knownVMs[jvmidx = i].name + 1; /* skip the - */
-            isVMType = 1;
-            *pargc = *pargc - 1;
-        }
-
-        /* Did the user specify an "alternate" VM? */
-        else if (strncmp(arg, "-XXaltjvm=", 10) == 0 || strncmp(arg, "-J-XXaltjvm=", 12) == 0) {
-            isVMType = 1;
-            jvmtype = arg+((arg[1]=='X')? 10 : 12);
-            jvmidx = -1;
-        }
-
-        if (!isVMType) {
-            newArgv[newArgvIdx++] = arg;
-        }
-    }
-
-    /*
-     * 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
-     * argc.
-     */
-    while (argi < argc) {
-        newArgv[newArgvIdx++] = (*argv)[argi];
-        argi++;
-    }
-
-    /* argv is null-terminated */
-    newArgv[newArgvIdx] = 0;
-
-    /* Copy back argv */
-    *argv = newArgv;
-    *pargc = newArgvIdx;
-
-    /* use the default VM type if not specified (no alias processing) */
-    if (jvmtype == NULL) {
-      char* result = knownVMs[0].name+1;
-      /* Use a different VM type if we are on a server class machine? */
-      if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) &&
-          (ServerClassMachine() == JNI_TRUE)) {
-        result = knownVMs[0].server_class+1;
-      }
-      if (_launcher_debug) {
-        printf("Default VM: %s\n", result);
-      }
-      return result;
-    }
-
-    /* if using an alternate VM, no alias processing */
-    if (jvmidx < 0)
-      return jvmtype;
-
-    /* Resolve aliases first */
-    {
-      int loopCount = 0;
-      while (knownVMs[jvmidx].flag == VM_ALIASED_TO) {
-        int nextIdx = KnownVMIndex(knownVMs[jvmidx].alias);
-
-        if (loopCount > knownVMsCount) {
-          if (!speculative) {
-            ReportErrorMessage("Error: Corrupt jvm.cfg file; cycle in alias list.",
-                               JNI_TRUE);
-            exit(1);
-          } else {
-            return "ERROR";
-            /* break; */
-          }
-        }
-
-        if (nextIdx < 0) {
-          if (!speculative) {
-            ReportErrorMessage2("Error: Unable to resolve VM alias %s",
-                                knownVMs[jvmidx].alias, JNI_TRUE);
-            exit(1);
-          } else {
-            return "ERROR";
-          }
-        }
-        jvmidx = nextIdx;
-        jvmtype = knownVMs[jvmidx].name+1;
-        loopCount++;
-      }
-    }
-
-    switch (knownVMs[jvmidx].flag) {
-    case VM_WARN:
-        if (!speculative) {
-            fprintf(stderr, "Warning: %s VM not supported; %s VM will be used\n",
-                    jvmtype, knownVMs[0].name + 1);
-        }
-        /* fall through */
-    case VM_IGNORE:
-        jvmtype = knownVMs[jvmidx=0].name + 1;
-        /* fall through */
-    case VM_KNOWN:
-        break;
-    case VM_ERROR:
-        if (!speculative) {
-            ReportErrorMessage2("Error: %s VM not supported", jvmtype, JNI_TRUE);
-            exit(1);
-        } else {
-            return "ERROR";
-        }
-    }
-
-    return jvmtype;
-}
-#endif /* ifndef GAMMA */
-
-/*
- * Adds a new VM option with the given given name and value.
- */
-static void
-AddOption(char *str, void *info)
-{
-    /*
-     * Expand options array if needed to accommodate at least one more
-     * VM option.
-     */
-    if (numOptions >= maxOptions) {
-        if (options == 0) {
-            maxOptions = 4;
-            options = MemAlloc(maxOptions * sizeof(JavaVMOption));
-        } else {
-            JavaVMOption *tmp;
-            maxOptions *= 2;
-            tmp = MemAlloc(maxOptions * sizeof(JavaVMOption));
-            memcpy(tmp, options, numOptions * sizeof(JavaVMOption));
-            free(options);
-            options = tmp;
-        }
-    }
-    options[numOptions].optionString = str;
-    options[numOptions++].extraInfo = info;
-}
-
-static void
-SetClassPath(char *s)
-{
-    char *def = MemAlloc(strlen(s) + 40);
-    sprintf(def, "-Djava.class.path=%s", s);
-    AddOption(def, NULL);
-}
-
-#ifndef GAMMA
-/*
- * 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.
- */
-static void
-SelectVersion(int argc, char **argv, char **main_class)
-{
-    char    *arg;
-    char    **new_argv;
-    char    **new_argp;
-    char    *operand;
-    char    *version = NULL;
-    char    *jre = NULL;
-    int     jarflag = 0;
-    int     restrict_search = -1;               /* -1 implies not known */
-    manifest_info info;
-    char    env_entry[MAXNAMELEN + 24] = ENV_ENTRY "=";
-    char    *env_in;
-    int     res;
-
-    /*
-     * If the version has already been selected, set *main_class
-     * with the value passed through the environment (if any) and
-     * simply return.
-     */
-    if ((env_in = getenv(ENV_ENTRY)) != NULL) {
-        if (*env_in != '\0')
-            *main_class = strdup(env_in);
-        return;
-    }
-
-    /*
-     * Scan through the arguments for options relevant to multiple JRE
-     * support.  For reference, the command line syntax is defined as:
-     *
-     * SYNOPSIS
-     *      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.
-     */
-    new_argv = MemAlloc((argc + 1) * sizeof(char*));
-    new_argv[0] = argv[0];
-    new_argp = &new_argv[1];
-    argc--;
-    argv++;
-    while ((arg = *argv) != 0 && *arg == '-') {
-        if (strncmp(arg, "-version:", 9) == 0) {
-            version = arg + 9;
-        } else if (strcmp(arg, "-jre-restrict-search") == 0) {
-            restrict_search = 1;
-        } else if (strcmp(arg, "-no-jre-restrict-search") == 0) {
-            restrict_search = 0;
-        } else {
-            if (strcmp(arg, "-jar") == 0)
-                jarflag = 1;
-            /* deal with "unfortunate" classpath syntax */
-            if ((strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) &&
-              (argc >= 2)) {
-                *new_argp++ = arg;
-                argc--;
-                argv++;
-                arg = *argv;
-            }
-            *new_argp++ = arg;
-        }
-        argc--;
-        argv++;
-    }
-    if (argc <= 0) {    /* No operand? Possibly legit with -[full]version */
-        operand = NULL;
-    } else {
-        argc--;
-        *new_argp++ = operand = *argv++;
-    }
-    while (argc-- > 0)  /* Copy over [argument...] */
-        *new_argp++ = *argv++;
-    *new_argp = NULL;
-
-    /*
-     * 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
-     * this data around.
-     */
-    if (jarflag && operand) {
-        if ((res = parse_manifest(operand, &info)) != 0) {
-            if (res == -1)
-                ReportErrorMessage2("Unable to access jarfile %s",
-                  operand, JNI_TRUE);
-            else
-                ReportErrorMessage2("Invalid or corrupt jarfile %s",
-                  operand, JNI_TRUE);
-            exit(1);
-        }
-    } else {
-        info.manifest_version = NULL;
-        info.main_class = NULL;
-        info.jre_version = NULL;
-        info.jre_restrict_search = 0;
-    }
-
-    /*
-     * The JRE-Version and JRE-Restrict-Search values (if any) from the
-     * manifest are overwritten by any specified on the command line.
-     */
-    if (version != NULL)
-        info.jre_version = version;
-    if (restrict_search != -1)
-        info.jre_restrict_search = restrict_search;
-
-    /*
-     * "Valid" returns (other than unrecoverable errors) follow.  Set
-     * main_class as a side-effect of this routine.
-     */
-    if (info.main_class != NULL)
-        *main_class = strdup(info.main_class);
-
-    /*
-     * If no version selection information is found either on the command
-     * line or in the manifest, simply return.
-     */
-    if (info.jre_version == NULL) {
-        free_manifest();
-        free(new_argv);
-        return;
-    }
-
-    /*
-     * Check for correct syntax of the version specification (JSR 56).
-     */
-    if (!valid_version_string(info.jre_version)) {
-        ReportErrorMessage2("Syntax error in version specification \"%s\"",
-          info.jre_version, JNI_TRUE);
-        exit(1);
-    }
-
-    /*
-     * 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
-     * JRE support.
-     */
-    jre = LocateJRE(&info);
-    if (_launcher_debug)
-        printf("JRE-Version = %s, JRE-Restrict-Search = %s Selected = %s\n",
-          (info.jre_version?info.jre_version:"null"),
-          (info.jre_restrict_search?"true":"false"), (jre?jre:"null"));
-    if (jre == NULL) {
-        if (acceptable_release(FULL_VERSION, info.jre_version)) {
-            free_manifest();
-            free(new_argv);
-            return;
-        } else {
-            ReportErrorMessage2(
-              "Unable to locate JRE meeting specification \"%s\"",
-              info.jre_version, JNI_TRUE);
-            exit(1);
-        }
-    }
-
-    /*
-     * 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
-     * times.
-     */
-    if (info.main_class != NULL)
-        (void)strcat(env_entry, info.main_class);
-    (void)putenv(env_entry);
-    ExecJRE(jre, new_argv);
-    free_manifest();
-    free(new_argv);
-    return;
-}
-#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
- * 0 for a normal exit.
- */
-static jboolean
-ParseArguments(int *pargc, char ***pargv, char **pjarfile,
-                       char **pclassname, int *pret)
-{
-    int argc = *pargc;
-    char **argv = *pargv;
-    jboolean jarflag = JNI_FALSE;
-    char *arg;
-
-    *pret = 1;
-    while ((arg = *argv) != 0 && *arg == '-') {
-        argv++; --argc;
-        if (strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) {
-            if (argc < 1) {
-                ReportErrorMessage2("%s requires class path specification",
-                                    arg, JNI_TRUE);
-                PrintUsage();
-                return JNI_FALSE;
-            }
-            SetClassPath(*argv);
-            argv++; --argc;
-        } else if (strcmp(arg, "-jar") == 0) {
-            jarflag = JNI_TRUE;
-        } else if (strcmp(arg, "-help") == 0 ||
-                   strcmp(arg, "-h") == 0 ||
-                   strcmp(arg, "-?") == 0) {
-            PrintUsage();
-            *pret = 0;
-            return JNI_FALSE;
-        } else if (strcmp(arg, "-version") == 0) {
-            printVersion = JNI_TRUE;
-            return JNI_TRUE;
-        } else if (strcmp(arg, "-showversion") == 0) {
-            showVersion = JNI_TRUE;
-        } else if (strcmp(arg, "-X") == 0) {
-            *pret = PrintXUsage();
-            return JNI_FALSE;
-/*
- * The following case provide backward compatibility with old-style
- * command line options.
- */
-        } else if (strcmp(arg, "-fullversion") == 0) {
-            fprintf(stderr, "%s full version \"%s\"\n", progname,
-                    FULL_VERSION);
-            *pret = 0;
-            return JNI_FALSE;
-        } else if (strcmp(arg, "-verbosegc") == 0) {
-            AddOption("-verbose:gc", NULL);
-        } else if (strcmp(arg, "-t") == 0) {
-            AddOption("-Xt", NULL);
-        } else if (strcmp(arg, "-tm") == 0) {
-            AddOption("-Xtm", NULL);
-        } else if (strcmp(arg, "-debug") == 0) {
-            AddOption("-Xdebug", NULL);
-        } else if (strcmp(arg, "-noclassgc") == 0) {
-            AddOption("-Xnoclassgc", NULL);
-        } else if (strcmp(arg, "-Xfuture") == 0) {
-            AddOption("-Xverify:all", NULL);
-        } else if (strcmp(arg, "-verify") == 0) {
-            AddOption("-Xverify:all", NULL);
-        } else if (strcmp(arg, "-verifyremote") == 0) {
-            AddOption("-Xverify:remote", NULL);
-        } else if (strcmp(arg, "-noverify") == 0) {
-            AddOption("-Xverify:none", NULL);
-        } else if (strcmp(arg, "-XXsuppressExitMessage") == 0) {
-            noExitErrorMessage = 1;
-        } else if (strncmp(arg, "-prof", 5) == 0) {
-            char *p = arg + 5;
-            char *tmp = MemAlloc(strlen(arg) + 50);
-            if (*p) {
-                sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1);
-            } else {
-                sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof");
-            }
-            AddOption(tmp, NULL);
-        } else if (strncmp(arg, "-ss", 3) == 0 ||
-                   strncmp(arg, "-oss", 4) == 0 ||
-                   strncmp(arg, "-ms", 3) == 0 ||
-                   strncmp(arg, "-mx", 3) == 0) {
-            char *tmp = MemAlloc(strlen(arg) + 6);
-            sprintf(tmp, "-X%s", arg + 1); /* skip '-' */
-            AddOption(tmp, NULL);
-        } else if (strcmp(arg, "-checksource") == 0 ||
-                   strcmp(arg, "-cs") == 0 ||
-                   strcmp(arg, "-noasyncgc") == 0) {
-            /* No longer supported */
-            fprintf(stderr,
-                    "Warning: %s option is no longer supported.\n",
-                    arg);
-        } else if (strncmp(arg, "-version:", 9) == 0 ||
-                   strcmp(arg, "-no-jre-restrict-search") == 0 ||
-                   strcmp(arg, "-jre-restrict-search") == 0) {
-            ; /* Ignore machine independent options already handled */
-        } else if (RemovableMachineDependentOption(arg) ) {
-            ; /* Do not pass option to vm. */
-        }
-        else {
-            AddOption(arg, NULL);
-        }
-    }
-
-    if (--argc >= 0) {
-        if (jarflag) {
-            *pjarfile = *argv++;
-            *pclassname = 0;
-        } else {
-            *pjarfile = 0;
-            *pclassname = *argv++;
-        }
-        *pargc = argc;
-        *pargv = argv;
-    }
-
-    return JNI_TRUE;
-}
-
-/*
- * Initializes the Java Virtual Machine. Also frees options array when
- * finished.
- */
-static jboolean
-InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn)
-{
-    JavaVMInitArgs args;
-    jint r;
-
-    memset(&args, 0, sizeof(args));
-    args.version  = JNI_VERSION_1_2;
-    args.nOptions = numOptions;
-    args.options  = options;
-    args.ignoreUnrecognized = JNI_FALSE;
-
-    if (_launcher_debug) {
-        int i = 0;
-        printf("JavaVM args:\n    ");
-        printf("version 0x%08lx, ", (long)args.version);
-        printf("ignoreUnrecognized is %s, ",
-               args.ignoreUnrecognized ? "JNI_TRUE" : "JNI_FALSE");
-        printf("nOptions is %ld\n", (long)args.nOptions);
-        for (i = 0; i < numOptions; i++)
-            printf("    option[%2d] = '%s'\n",
-                   i, args.options[i].optionString);
-    }
-
-    r = ifn->CreateJavaVM(pvm, (void **)penv, &args);
-    free(options);
-    return r == JNI_OK;
-}
-
-
-#define NULL_CHECK0(e) if ((e) == 0) return 0
-#define NULL_CHECK(e) if ((e) == 0) return
-
-/*
- * Returns a pointer to a block of at least 'size' bytes of memory.
- * Prints error message and exits if the memory could not be allocated.
- */
-void *
-MemAlloc(size_t size)
-{
-    void *p = malloc(size);
-    if (p == 0) {
-        perror("malloc");
-        exit(1);
-    }
-    return p;
-}
-
-static jstring platformEncoding = NULL;
-static jstring getPlatformEncoding(JNIEnv *env) {
-    if (platformEncoding == NULL) {
-        jstring propname = (*env)->NewStringUTF(env, "sun.jnu.encoding");
-        if (propname) {
-            jclass cls;
-            jmethodID mid;
-            NULL_CHECK0 (cls = FindBootStrapClass(env, "java/lang/System"));
-            NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
-                                   env, cls,
-                                   "getProperty",
-                                   "(Ljava/lang/String;)Ljava/lang/String;"));
-            platformEncoding = (*env)->CallStaticObjectMethod (
-                                    env, cls, mid, propname);
-        }
-    }
-    return platformEncoding;
-}
-
-static jboolean isEncodingSupported(JNIEnv *env, jstring enc) {
-    jclass cls;
-    jmethodID mid;
-    NULL_CHECK0 (cls = FindBootStrapClass(env, "java/nio/charset/Charset"));
-    NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
-                           env, cls,
-                           "isSupported",
-                           "(Ljava/lang/String;)Z"));
-    return (*env)->CallStaticBooleanMethod (env, cls, mid, enc);
-}
-
-/*
- * Returns a new Java string object for the specified platform string.
- */
-static jstring
-NewPlatformString(JNIEnv *env, char *s)
-{
-    int len = (int)strlen(s);
-    jclass cls;
-    jmethodID mid;
-    jbyteArray ary;
-    jstring enc;
-
-    if (s == NULL)
-        return 0;
-    enc = getPlatformEncoding(env);
-
-    ary = (*env)->NewByteArray(env, len);
-    if (ary != 0) {
-        jstring str = 0;
-        (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s);
-        if (!(*env)->ExceptionOccurred(env)) {
-#ifdef GAMMA
-            /* We support running JVM with older JDK, so here we have to deal */
-            /* with the case that sun.jnu.encoding is undefined (enc == NULL) */
-            if (enc != NULL && isEncodingSupported(env, enc) == JNI_TRUE) {
-#else
-            if (isEncodingSupported(env, enc) == JNI_TRUE) {
-#endif
-                NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
-                NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
-                                          "([BLjava/lang/String;)V"));
-                str = (*env)->NewObject(env, cls, mid, ary, enc);
-            } else {
-                /*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.
-                */
-                NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
-                NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
-                                          "([B)V"));
-                str = (*env)->NewObject(env, cls, mid, ary);
-            }
-            (*env)->DeleteLocalRef(env, ary);
-            return str;
-        }
-    }
-    return 0;
-}
-
-/*
- * Returns a new array of Java string objects for the specified
- * array of platform strings.
- */
-static jobjectArray
-NewPlatformStringArray(JNIEnv *env, char **strv, int strc)
-{
-    jarray cls;
-    jarray ary;
-    int i;
-
-    NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
-    NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0));
-    for (i = 0; i < strc; i++) {
-        jstring str = NewPlatformString(env, *strv++);
-        NULL_CHECK0(str);
-        (*env)->SetObjectArrayElement(env, ary, i, str);
-        (*env)->DeleteLocalRef(env, str);
-    }
-    return ary;
-}
-
-/*
- * Loads a class, convert the '.' to '/'.
- */
-static jclass
-LoadClass(JNIEnv *env, char *name)
-{
-    char *buf = MemAlloc(strlen(name) + 1);
-    char *s = buf, *t = name, c;
-    jclass cls;
-    jlong start, end;
-
-    if (_launcher_debug)
-        start = CounterGet();
-
-    do {
-        c = *t++;
-        *s++ = (c == '.') ? '/' : c;
-    } while (c != '\0');
-    // use the application class loader for main-class
-    cls = (*env)->FindClass(env, buf);
-    free(buf);
-
-    if (_launcher_debug) {
-        end   = CounterGet();
-        printf("%ld micro seconds to load main class\n",
-               (long)(jint)Counter2Micros(end-start));
-        printf("----_JAVA_LAUNCHER_DEBUG----\n");
-    }
-
-    return cls;
-}
-
-
-/*
- * Returns the main class name for the specified jar file.
- */
-static jstring
-GetMainClassName(JNIEnv *env, char *jarname)
-{
-#define MAIN_CLASS "Main-Class"
-    jclass cls;
-    jmethodID mid;
-    jobject jar, man, attr;
-    jstring str, result = 0;
-
-    NULL_CHECK0(cls = FindBootStrapClass(env, "java/util/jar/JarFile"));
-    NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
-                                          "(Ljava/lang/String;)V"));
-    NULL_CHECK0(str = NewPlatformString(env, jarname));
-    NULL_CHECK0(jar = (*env)->NewObject(env, cls, mid, str));
-    NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "getManifest",
-                                          "()Ljava/util/jar/Manifest;"));
-    man = (*env)->CallObjectMethod(env, jar, mid);
-    if (man != 0) {
-        NULL_CHECK0(mid = (*env)->GetMethodID(env,
-                                    (*env)->GetObjectClass(env, man),
-                                    "getMainAttributes",
-                                    "()Ljava/util/jar/Attributes;"));
-        attr = (*env)->CallObjectMethod(env, man, mid);
-        if (attr != 0) {
-            NULL_CHECK0(mid = (*env)->GetMethodID(env,
-                                    (*env)->GetObjectClass(env, attr),
-                                    "getValue",
-                                    "(Ljava/lang/String;)Ljava/lang/String;"));
-            NULL_CHECK0(str = NewPlatformString(env, MAIN_CLASS));
-            result = (*env)->CallObjectMethod(env, attr, mid, str);
-        }
-    }
-    return result;
-}
-
-#ifdef JAVA_ARGS
-static char *java_args[] = JAVA_ARGS;
-static char *app_classpath[] = APP_CLASSPATH;
-
-/*
- * For tools convert 'javac -J-ms32m' to 'java -ms32m ...'
- */
-static void
-TranslateDashJArgs(int *pargc, char ***pargv)
-{
-    const int NUM_ARGS = (sizeof(java_args) / sizeof(char *));
-    int argc = *pargc;
-    char **argv = *pargv;
-    int nargc = argc + NUM_ARGS;
-    char **nargv = MemAlloc((nargc + 1) * sizeof(char *));
-    int i;
-
-    *pargc = nargc;
-    *pargv = nargv;
-
-    /* Copy the VM arguments (i.e. prefixed with -J) */
-    for (i = 0; i < NUM_ARGS; i++) {
-        char *arg = java_args[i];
-        if (arg[0] == '-' && arg[1] == 'J') {
-            *nargv++ = arg + 2;
-        }
-    }
-
-    for (i = 0; i < argc; i++) {
-        char *arg = argv[i];
-        if (arg[0] == '-' && arg[1] == 'J') {
-            if (arg[2] == '\0') {
-                ReportErrorMessage("Error: the -J option should not be "
-                                   "followed by a space.", JNI_TRUE);
-                exit(1);
-            }
-            *nargv++ = arg + 2;
-        }
-    }
-
-    /* Copy the rest of the arguments */
-    for (i = 0; i < NUM_ARGS; i++) {
-        char *arg = java_args[i];
-        if (arg[0] != '-' || arg[1] != 'J') {
-            *nargv++ = arg;
-        }
-    }
-    for (i = 0; i < argc; i++) {
-        char *arg = argv[i];
-        if (arg[0] != '-' || arg[1] != 'J') {
-            *nargv++ = arg;
-        }
-    }
-    *nargv = 0;
-}
-
-/*
- * For our tools, we try to add 3 VM options:
- *      -Denv.class.path=<envcp>
- *      -Dapplication.home=<apphome>
- *      -Djava.class.path=<appcp>
- * <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 classes (sun.tools.javac.Main) only if they explicitly add
- *           tools.jar to CLASSPATH.
- * <apphome> is the directory where the application is installed.
- * <appcp>   is the classpath to where our apps' classfiles are.
- */
-static jboolean
-AddApplicationOptions()
-{
-    const int NUM_APP_CLASSPATH = (sizeof(app_classpath) / sizeof(char *));
-    char *s, *envcp, *appcp, *apphome;
-    char home[MAXPATHLEN]; /* application home */
-    char separator[] = { PATH_SEPARATOR, '\0' };
-    int size, i;
-    int strlenHome;
-
-    s = getenv("CLASSPATH");
-    if (s) {
-        /* 40 for -Denv.class.path= */
-        envcp = (char *)MemAlloc(strlen(s) + 40);
-        sprintf(envcp, "-Denv.class.path=%s", s);
-        AddOption(envcp, NULL);
-    }
-
-    if (!GetApplicationHome(home, sizeof(home))) {
-        ReportErrorMessage("Can't determine application home", JNI_TRUE);
-        return JNI_FALSE;
-    }
-
-    /* 40 for '-Dapplication.home=' */
-    apphome = (char *)MemAlloc(strlen(home) + 40);
-    sprintf(apphome, "-Dapplication.home=%s", home);
-    AddOption(apphome, NULL);
-
-    /* How big is the application's classpath? */
-    size = 40;                                 /* 40: "-Djava.class.path=" */
-    strlenHome = (int)strlen(home);
-    for (i = 0; i < NUM_APP_CLASSPATH; i++) {
-        size += strlenHome + (int)strlen(app_classpath[i]) + 1; /* 1: separator */
-    }
-    appcp = (char *)MemAlloc(size + 1);
-    strcpy(appcp, "-Djava.class.path=");
-    for (i = 0; i < NUM_APP_CLASSPATH; i++) {
-        strcat(appcp, home);                    /* c:\program files\myapp */
-        strcat(appcp, app_classpath[i]);        /* \lib\myapp.jar         */
-        strcat(appcp, separator);               /* ;                      */
-    }
-    appcp[strlen(appcp)-1] = '\0';  /* remove trailing path separator */
-    AddOption(appcp, NULL);
-    return JNI_TRUE;
-}
-#endif
-
-/*
- * 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.
- */
-void
-SetJavaCommandLineProp(char *classname, char *jarfile,
-                       int argc, char **argv)
-{
-
-    int i = 0;
-    size_t len = 0;
-    char* javaCommand = NULL;
-    char* dashDstr = "-Dsun.java.command=";
-
-    if (classname == NULL && jarfile == NULL) {
-        /* unexpected, one of these should be set. just return without
-         * setting the property
-         */
-        return;
-    }
-
-    /* if the class name is not set, then use the jarfile name */
-    if (classname == NULL) {
-        classname = jarfile;
-    }
-
-    /* determine the amount of memory to allocate assuming
-     * the individual components will be space separated
-     */
-    len = strlen(classname);
-    for (i = 0; i < argc; i++) {
-        len += strlen(argv[i]) + 1;
-    }
-
-    /* allocate the memory */
-    javaCommand = (char*) MemAlloc(len + strlen(dashDstr) + 1);
-
-    /* build the -D string */
-    *javaCommand = '\0';
-    strcat(javaCommand, dashDstr);
-    strcat(javaCommand, classname);
-
-    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.
-         */
-        strcat(javaCommand, " ");
-        strcat(javaCommand, argv[i]);
-    }
-
-    AddOption(javaCommand, NULL);
-}
-
-/*
- * JVM wants to know launcher type, so tell it.
- */
-#ifdef GAMMA
-void SetJavaLauncherProp() {
-  AddOption("-Dsun.java.launcher=" LAUNCHER_TYPE, NULL);
-}
-#endif
-
-/*
- * Prints the version information from the java.version and other properties.
- */
-static void
-PrintJavaVersion(JNIEnv *env)
-{
-    jclass ver;
-    jmethodID print;
-
-    NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version"));
-    NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, "print", "()V"));
-
-    (*env)->CallStaticVoidMethod(env, ver, print);
-}
-
-/*
- * Prints default usage message.
- */
-static void
-PrintUsage(void)
-{
-    int i;
-
-    fprintf(stdout,
-        "Usage: %s [-options] class [args...]\n"
-        "           (to execute a class)\n"
-        "   or  %s [-options] -jar jarfile [args...]\n"
-        "           (to execute a jar file)\n"
-        "\n"
-        "where options include:\n",
-        progname,
-        progname);
-
-#ifndef GAMMA
-    PrintMachineDependentOptions();
-
-    if ((knownVMs[0].flag == VM_KNOWN) ||
-        (knownVMs[0].flag == VM_IF_SERVER_CLASS)) {
-      fprintf(stdout, "    %s\t  to select the \"%s\" VM\n",
-              knownVMs[0].name, knownVMs[0].name+1);
-    }
-    for (i=1; i<knownVMsCount; i++) {
-        if (knownVMs[i].flag == VM_KNOWN)
-            fprintf(stdout, "    %s\t  to select the \"%s\" VM\n",
-                    knownVMs[i].name, knownVMs[i].name+1);
-    }
-    for (i=1; i<knownVMsCount; i++) {
-        if (knownVMs[i].flag == VM_ALIASED_TO)
-            fprintf(stdout, "    %s\t  is a synonym for "
-                    "the \"%s\" VM  [deprecated]\n",
-                    knownVMs[i].name, knownVMs[i].alias+1);
-    }
-
-    /* The first known VM is the default */
-    {
-      const char* defaultVM   = knownVMs[0].name+1;
-      const char* punctuation = ".";
-      const char* reason      = "";
-      if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) &&
-          (ServerClassMachine() == JNI_TRUE)) {
-        defaultVM = knownVMs[0].server_class+1;
-        punctuation = ", ";
-        reason = "because you are running on a server-class machine.\n";
-      }
-      fprintf(stdout, "                  The default VM is %s%s\n",
-              defaultVM, punctuation);
-      fprintf(stdout, "                  %s\n",
-              reason);
-    }
-#endif /* ifndef GAMMA */
-
-    fprintf(stdout,
-"    -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"
-"    -D<name>=<value>\n"
-"                  set a system property\n"
-"    -verbose[:class|gc|jni]\n"
-"                  enable verbose output\n"
-"    -version      print product version and exit\n"
-"    -version:<value>\n"
-"                  require the specified version to run\n"
-"    -showversion  print product version and continue\n"
-"    -jre-restrict-search | -jre-no-restrict-search\n"
-"                  include/exclude user private JREs in the version search\n"
-"    -? -help      print this help message\n"
-"    -X            print help on non-standard options\n"
-"    -ea[:<packagename>...|:<classname>]\n"
-"    -enableassertions[:<packagename>...|:<classname>]\n"
-"                  enable assertions\n"
-"    -da[:<packagename>...|:<classname>]\n"
-"    -disableassertions[:<packagename>...|:<classname>]\n"
-"                  disable assertions\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"
-
-            ,PATH_SEPARATOR);
-}
-
-/*
- * Print usage message for -X options.
- */
-static jint
-PrintXUsage(void)
-{
-    char path[MAXPATHLEN];
-    char buf[128];
-    size_t n;
-    FILE *fp;
-
-    GetXUsagePath(path, sizeof(path));
-    fp = fopen(path, "r");
-    if (fp == 0) {
-        fprintf(stderr, "Can't open %s\n", path);
-        return 1;
-    }
-    while ((n = fread(buf, 1, sizeof(buf), fp)) != 0) {
-        fwrite(buf, 1, n, stdout);
-    }
-    fclose(fp);
-    return 0;
-}
-
-#ifndef GAMMA
-
-/*
- * 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:
- *
- *     jvmcfg         :=  { vmLine }
- *     vmLine         :=  knownLine
- *                    |   aliasLine
- *                    |   warnLine
- *                    |   ignoreLine
- *                    |   errorLine
- *                    |   predicateLine
- *                    |   commentLine
- *     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
- *     flag           :=  "-" identifier
- *
- * 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
- * mechanism.
- */
-jint
-ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative)
-{
-    FILE *jvmCfg;
-    char jvmCfgName[MAXPATHLEN+20];
-    char line[MAXPATHLEN+20];
-    int cnt = 0;
-    int lineno = 0;
-    jlong start, end;
-    int vmType;
-    char *tmpPtr;
-    char *altVMName;
-    char *serverClassVMName;
-    static char *whiteSpace = " \t";
-    if (_launcher_debug) {
-        start = CounterGet();
-    }
-
-    strcpy(jvmCfgName, jrepath);
-    strcat(jvmCfgName, FILESEP "lib" FILESEP);
-    strcat(jvmCfgName, arch);
-    strcat(jvmCfgName, FILESEP "jvm.cfg");
-
-    jvmCfg = fopen(jvmCfgName, "r");
-    if (jvmCfg == NULL) {
-      if (!speculative) {
-        ReportErrorMessage2("Error: could not open `%s'", jvmCfgName,
-                            JNI_TRUE);
-        exit(1);
-      } else {
-        return -1;
-      }
-    }
-    while (fgets(line, sizeof(line), jvmCfg) != NULL) {
-        vmType = VM_UNKNOWN;
-        lineno++;
-        if (line[0] == '#')
-            continue;
-        if (line[0] != '-') {
-            fprintf(stderr, "Warning: no leading - on line %d of `%s'\n",
-                    lineno, jvmCfgName);
-        }
-        if (cnt >= knownVMsLimit) {
-            GrowKnownVMs(cnt);
-        }
-        line[strlen(line)-1] = '\0'; /* remove trailing newline */
-        tmpPtr = line + strcspn(line, whiteSpace);
-        if (*tmpPtr == 0) {
-            fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n",
-                    lineno, jvmCfgName);
-        } else {
-            /* Null-terminate this string for strdup below */
-            *tmpPtr++ = 0;
-            tmpPtr += strspn(tmpPtr, whiteSpace);
-            if (*tmpPtr == 0) {
-                fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n",
-                        lineno, jvmCfgName);
-            } else {
-                if (!strncmp(tmpPtr, "KNOWN", strlen("KNOWN"))) {
-                    vmType = VM_KNOWN;
-                } else if (!strncmp(tmpPtr, "ALIASED_TO", strlen("ALIASED_TO"))) {
-                    tmpPtr += strcspn(tmpPtr, whiteSpace);
-                    if (*tmpPtr != 0) {
-                        tmpPtr += strspn(tmpPtr, whiteSpace);
-                    }
-                    if (*tmpPtr == 0) {
-                        fprintf(stderr, "Warning: missing VM alias on line %d of `%s'\n",
-                                lineno, jvmCfgName);
-                    } else {
-                        /* Null terminate altVMName */
-                        altVMName = tmpPtr;
-                        tmpPtr += strcspn(tmpPtr, whiteSpace);
-                        *tmpPtr = 0;
-                        vmType = VM_ALIASED_TO;
-                    }
-                } else if (!strncmp(tmpPtr, "WARN", strlen("WARN"))) {
-                    vmType = VM_WARN;
-                } else if (!strncmp(tmpPtr, "IGNORE", strlen("IGNORE"))) {
-                    vmType = VM_IGNORE;
-                } else if (!strncmp(tmpPtr, "ERROR", strlen("ERROR"))) {
-                    vmType = VM_ERROR;
-                } else if (!strncmp(tmpPtr,
-                                    "IF_SERVER_CLASS",
-                                    strlen("IF_SERVER_CLASS"))) {
-                    tmpPtr += strcspn(tmpPtr, whiteSpace);
-                    if (*tmpPtr != 0) {
-                        tmpPtr += strspn(tmpPtr, whiteSpace);
-                    }
-                    if (*tmpPtr == 0) {
-                        fprintf(stderr, "Warning: missing server class VM on line %d of `%s'\n",
-                                lineno, jvmCfgName);
-                    } else {
-                        /* Null terminate server class VM name */
-                        serverClassVMName = tmpPtr;
-                        tmpPtr += strcspn(tmpPtr, whiteSpace);
-                        *tmpPtr = 0;
-                        vmType = VM_IF_SERVER_CLASS;
-                    }
-                } else {
-                    fprintf(stderr, "Warning: unknown VM type on line %d of `%s'\n",
-                            lineno, &jvmCfgName[0]);
-                    vmType = VM_KNOWN;
-                }
-            }
-        }
-
-        if (_launcher_debug)
-            printf("jvm.cfg[%d] = ->%s<-\n", cnt, line);
-        if (vmType != VM_UNKNOWN) {
-            knownVMs[cnt].name = strdup(line);
-            knownVMs[cnt].flag = vmType;
-            switch (vmType) {
-            default:
-                break;
-            case VM_ALIASED_TO:
-                knownVMs[cnt].alias = strdup(altVMName);
-                if (_launcher_debug) {
-                    printf("    name: %s  vmType: %s  alias: %s\n",
-                           knownVMs[cnt].name, "VM_ALIASED_TO", knownVMs[cnt].alias);
-                }
-                break;
-            case VM_IF_SERVER_CLASS:
-                knownVMs[cnt].server_class = strdup(serverClassVMName);
-                if (_launcher_debug) {
-                    printf("    name: %s  vmType: %s  server_class: %s\n",
-                           knownVMs[cnt].name, "VM_IF_SERVER_CLASS", knownVMs[cnt].server_class);
-                }
-                break;
-            }
-            cnt++;
-        }
-    }
-    fclose(jvmCfg);
-    knownVMsCount = cnt;
-
-    if (_launcher_debug) {
-        end   = CounterGet();
-        printf("%ld micro seconds to parse jvm.cfg\n",
-               (long)(jint)Counter2Micros(end-start));
-    }
-
-    return cnt;
-}
-
-
-static void
-GrowKnownVMs(int minimum)
-{
-    struct vmdesc* newKnownVMs;
-    int newMax;
-
-    newMax = (knownVMsLimit == 0 ? INIT_MAX_KNOWN_VMS : (2 * knownVMsLimit));
-    if (newMax <= minimum) {
-        newMax = minimum;
-    }
-    newKnownVMs = (struct vmdesc*) MemAlloc(newMax * sizeof(struct vmdesc));
-    if (knownVMs != NULL) {
-        memcpy(newKnownVMs, knownVMs, knownVMsLimit * sizeof(struct vmdesc));
-    }
-    free(knownVMs);
-    knownVMs = newKnownVMs;
-    knownVMsLimit = newMax;
-}
-
-
-/* Returns index of VM or -1 if not found */
-static int
-KnownVMIndex(const char* name)
-{
-    int i;
-    if (strncmp(name, "-J", 2) == 0) name += 2;
-    for (i = 0; i < knownVMsCount; i++) {
-        if (!strcmp(name, knownVMs[i].name)) {
-            return i;
-        }
-    }
-    return -1;
-}
-
-static void
-FreeKnownVMs()
-{
-    int i;
-    for (i = 0; i < knownVMsCount; i++) {
-        free(knownVMs[i].name);
-        knownVMs[i].name = NULL;
-    }
-    free(knownVMs);
-}
-
-#endif /* ifndef GAMMA */
--- a/hotspot/src/os/linux/launcher/java.h	Thu Dec 02 20:01:47 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK,
- * search "GAMMA" for gamma specific changes.
- */
-
-#ifndef _JAVA_H_
-#define _JAVA_H_
-
-/*
- * Get system specific defines.
- */
-#include "jni.h"
-#include "java_md.h"
-
-/*
- * Pointers to the needed JNI invocation API, initialized by LoadJavaVM.
- */
-typedef jint (JNICALL *CreateJavaVM_t)(JavaVM **pvm, void **env, void *args);
-typedef jint (JNICALL *GetDefaultJavaVMInitArgs_t)(void *args);
-
-typedef struct {
-    CreateJavaVM_t CreateJavaVM;
-    GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs;
-} InvocationFunctions;
-
-/*
- * Prototypes for launcher functions in the system specific java_md.c.
- */
-
-jboolean
-LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn);
-
-void
-GetXUsagePath(char *buf, jint bufsize);
-
-jboolean
-GetApplicationHome(char *buf, jint bufsize);
-
-const char *
-GetArch();
-
-void CreateExecutionEnvironment(int *_argc,
-                                       char ***_argv,
-                                       char jrepath[],
-                                       jint so_jrepath,
-                                       char jvmpath[],
-                                       jint so_jvmpath,
-                                       char **original_argv);
-
-/*
- * Report an error message to stderr or a window as appropriate.  The
- * flag always is set to JNI_TRUE if message is to be reported to both
- * strerr and windows and set to JNI_FALSE if the message should only
- * be sent to a window.
- */
-void ReportErrorMessage(char * message, jboolean always);
-void ReportErrorMessage2(char * format, char * string, jboolean always);
-
-/*
- * Report an exception which terminates the vm to stderr or a window
- * as appropriate.
- */
-void ReportExceptionDescription(JNIEnv * env);
-
-jboolean RemovableMachineDependentOption(char * option);
-void PrintMachineDependentOptions();
-
-/*
- * Functions defined in java.c and used in java_md.c.
- */
-jint ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative);
-char *CheckJvmType(int *argc, char ***argv, jboolean speculative);
-void* MemAlloc(size_t size);
-
-/*
- * Make launcher spit debug output.
- */
-extern jboolean _launcher_debug;
-/*
- * This allows for finding classes from the VM's bootstrap class loader
- * directly, FindClass uses the application class loader internally, this will
- * cause unnecessary searching of the classpath for the required classes.
- */
-typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env,
-                                                const char *name,
-                                                jboolean throwError));
-
-jclass FindBootStrapClass(JNIEnv *env, const char *classname);
-
-#endif /* _JAVA_H_ */
--- a/hotspot/src/os/linux/launcher/java_md.c	Thu Dec 02 20:01:47 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1852 +0,0 @@
-/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK,
- * search "GAMMA" for gamma specific changes.
- */
-
-#include "java.h"
-#include <dirent.h>
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/types.h>
-
-#ifndef GAMMA
-#include "manifest_info.h"
-#include "version_comp.h"
-#endif
-
-#define JVM_DLL "libjvm.so"
-#define JAVA_DLL "libjava.so"
-
-#ifndef GAMMA   /* launcher.make defines ARCH */
-
-/*
- * If a processor / os combination has the ability to run binaries of
- * two data models and cohabitation of jre/jdk bits with both data
- * models is supported, then DUAL_MODE is defined.  When DUAL_MODE is
- * defined, the architecture names for the narrow and wide version of
- * the architecture are defined in BIG_ARCH and SMALL_ARCH.  Currently
- * only Solaris on sparc/sparcv9 and i586/amd64 is DUAL_MODE; linux
- * i586/amd64 could be defined as DUAL_MODE but that is not the
- * current policy.
- */
-
-#ifdef _LP64
-
-#  ifdef ia64
-#    define ARCH "ia64"
-#  elif defined(amd64)
-#    define ARCH "amd64"
-#  elif defined(__sparc)
-#    define ARCH "sparcv9"
-#  else
-#    define ARCH "unknown" /* unknown 64-bit architecture */
-#  endif
-
-#else /* 32-bit data model */
-
-#  ifdef i586
-#    define ARCH "i386"
-#  elif defined(__sparc)
-#    define ARCH "sparc"
-#  elif defined(arm)
-#    define ARCH "arm"
-#  elif defined(PPC)
-#    define ARCH "ppc"
-#  endif
-
-#endif /* _LP64 */
-
-#ifdef __sun
-#  define DUAL_MODE
-#  ifdef __sparc
-#    define BIG_ARCH "sparcv9"
-#    define SMALL_ARCH "sparc"
-#  else
-#    define BIG_ARCH "amd64"
-#    define SMALL_ARCH "i386"
-#  endif
-#  include <sys/systeminfo.h>
-#  include <sys/elf.h>
-#  include <stdio.h>
-#else
-#  ifndef ARCH
-#    include <sys/systeminfo.h>
-#  endif
-#endif
-
-#endif /* ifndef GAMMA */
-
-/* pointer to environment */
-extern char **environ;
-
-#ifndef GAMMA
-
-/*
- *      A collection of useful strings. One should think of these as #define
- *      entries, but actual strings can be more efficient (with many compilers).
- */
-#ifdef __linux__
-static const char *system_dir   = "/usr/java";
-static const char *user_dir     = "/java";
-#else /* Solaris */
-static const char *system_dir   = "/usr/jdk";
-static const char *user_dir     = "/jdk";
-#endif
-
-#endif  /* ifndef GAMMA */
-
-/*
- * Flowchart of launcher execs and options processing on unix
- *
- * The selection of the proper vm shared library to open depends on
- * several classes of command line options, including vm "flavor"
- * options (-client, -server) and the data model options, -d32  and
- * -d64, as well as a version specification which may have come from
- * the command line or from the manifest of an executable jar file.
- * The vm selection options are not passed to the running
- * virtual machine; they must be screened out by the launcher.
- *
- * The version specification (if any) is processed first by the
- * platform independent routine SelectVersion.  This may result in
- * the exec of the specified launcher version.
- *
- * Typically, the launcher execs at least once to ensure a suitable
- * LD_LIBRARY_PATH is in effect for the process.  The first exec
- * screens out all the data model options; leaving the choice of data
- * model implicit in the binary selected to run.  However, in case no
- * exec is done, the data model options are screened out before the vm
- * is invoked.
- *
- *  incoming argv ------------------------------
- *  |                                          |
- * \|/                                         |
- * CheckJVMType                                |
- * (removes -client, -server, etc.)            |
- *                                            \|/
- *                                            CreateExecutionEnvironment
- *                                            (removes -d32 and -d64,
- *                                             determines desired data model,
- *                                             sets up LD_LIBRARY_PATH,
- *                                             and exec's)
- *                                             |
- *  --------------------------------------------
- *  |
- * \|/
- * exec child 1 incoming argv -----------------
- *  |                                          |
- * \|/                                         |
- * CheckJVMType                                |
- * (removes -client, -server, etc.)            |
- *  |                                         \|/
- *  |                                          CreateExecutionEnvironment
- *  |                                          (verifies desired data model
- *  |                                           is running and acceptable
- *  |                                           LD_LIBRARY_PATH;
- *  |                                           no-op in child)
- *  |
- * \|/
- * TranslateDashJArgs...
- * (Prepare to pass args to vm)
- *  |
- *  |
- *  |
- * \|/
- * ParseArguments
- * (ignores -d32 and -d64,
- *  processes version options,
- *  creates argument list for vm,
- *  etc.)
- *
- */
-
-static char *SetExecname(char **argv);
-static char * GetExecname();
-static jboolean GetJVMPath(const char *jrepath, const char *jvmtype,
-                           char *jvmpath, jint jvmpathsize, char * arch);
-static jboolean GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative);
-
-const char *
-GetArch()
-{
-    static char *arch = NULL;
-    static char buf[12];
-    if (arch) {
-        return arch;
-    }
-
-#ifdef ARCH
-    strcpy(buf, ARCH);
-#else
-    sysinfo(SI_ARCHITECTURE, buf, sizeof(buf));
-#endif
-    arch = buf;
-    return arch;
-}
-
-void
-CreateExecutionEnvironment(int *_argcp,
-                           char ***_argvp,
-                           char jrepath[],
-                           jint so_jrepath,
-                           char jvmpath[],
-                           jint so_jvmpath,
-                           char **original_argv) {
-  /*
-   * First, determine if we are running the desired data model.  If we
-   * are running the desired data model, all the error messages
-   * associated with calling GetJREPath, ReadKnownVMs, etc. should be
-   * output.  However, if we are not running the desired data model,
-   * some of the errors should be suppressed since it is more
-   * informative to issue an error message based on whether or not the
-   * os/processor combination has dual mode capabilities.
-   */
-
-    char *execname = NULL;
-    int original_argc = *_argcp;
-    jboolean jvmpathExists;
-
-    /* Compute the name of the executable */
-    execname = SetExecname(*_argvp);
-
-#ifndef GAMMA
-    /* Set the LD_LIBRARY_PATH environment variable, check data model
-       flags, and exec process, if needed */
-    {
-      char *arch        = (char *)GetArch(); /* like sparc or sparcv9 */
-      char * jvmtype    = NULL;
-      int argc          = *_argcp;
-      char **argv       = original_argv;
-
-      char *runpath     = NULL; /* existing effective LD_LIBRARY_PATH
-                                   setting */
-
-      int running       =       /* What data model is being ILP32 =>
-                                   32 bit vm; LP64 => 64 bit vm */
-#ifdef _LP64
-        64;
-#else
-      32;
-#endif
-
-      int wanted        = running;      /* What data mode is being
-                                           asked for? Current model is
-                                           fine unless another model
-                                           is asked for */
-
-      char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */
-      char* newpath     = NULL; /* path on new LD_LIBRARY_PATH */
-      char* lastslash   = NULL;
-
-      char** newenvp    = NULL; /* current environment */
-
-      char** newargv    = NULL;
-      int    newargc    = 0;
-#ifdef __sun
-      char*  dmpath     = NULL;  /* data model specific LD_LIBRARY_PATH,
-                                    Solaris only */
-#endif
-
-      /*
-       * Starting in 1.5, all unix platforms accept the -d32 and -d64
-       * options.  On platforms where only one data-model is supported
-       * (e.g. ia-64 Linux), using the flag for the other data model is
-       * an error and will terminate the program.
-       */
-
-      { /* open new scope to declare local variables */
-        int i;
-
-        newargv = (char **)MemAlloc((argc+1) * sizeof(*newargv));
-        newargv[newargc++] = argv[0];
-
-        /* scan for data model arguments and remove from argument list;
-           last occurrence determines desired data model */
-        for (i=1; i < argc; i++) {
-
-          if (strcmp(argv[i], "-J-d64") == 0 || strcmp(argv[i], "-d64") == 0) {
-            wanted = 64;
-            continue;
-          }
-          if (strcmp(argv[i], "-J-d32") == 0 || strcmp(argv[i], "-d32") == 0) {
-            wanted = 32;
-            continue;
-          }
-          newargv[newargc++] = argv[i];
-
-#ifdef JAVA_ARGS
-          if (argv[i][0] != '-')
-            continue;
-#else
-          if (strcmp(argv[i], "-classpath") == 0 || strcmp(argv[i], "-cp") == 0) {
-            i++;
-            if (i >= argc) break;
-            newargv[newargc++] = argv[i];
-            continue;
-          }
-          if (argv[i][0] != '-') { i++; break; }
-#endif
-        }
-
-        /* copy rest of args [i .. argc) */
-        while (i < argc) {
-          newargv[newargc++] = argv[i++];
-        }
-        newargv[newargc] = NULL;
-
-        /*
-         * newargv has all proper arguments here
-         */
-
-        argc = newargc;
-        argv = newargv;
-      }
-
-      /* If the data model is not changing, it is an error if the
-         jvmpath does not exist */
-      if (wanted == running) {
-        /* Find out where the JRE is that we will be using. */
-        if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) {
-          fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n");
-          exit(2);
-        }
-
-        /* Find the specified JVM type */
-        if (ReadKnownVMs(jrepath, arch, JNI_FALSE) < 1) {
-          fprintf(stderr, "Error: no known VMs. (check for corrupt jvm.cfg file)\n");
-          exit(1);
-        }
-
-        jvmpath[0] = '\0';
-        jvmtype = CheckJvmType(_argcp, _argvp, JNI_FALSE);
-
-        if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch )) {
-          fprintf(stderr, "Error: no `%s' JVM at `%s'.\n", jvmtype, jvmpath);
-          exit(4);
-        }
-      } else {  /* do the same speculatively or exit */
-#ifdef DUAL_MODE
-        if (running != wanted) {
-          /* Find out where the JRE is that we will be using. */
-          if (!GetJREPath(jrepath, so_jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH), JNI_TRUE)) {
-            goto EndDataModelSpeculate;
-          }
-
-          /*
-           * Read in jvm.cfg for target data model and process vm
-           * selection options.
-           */
-          if (ReadKnownVMs(jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH), JNI_TRUE) < 1) {
-            goto EndDataModelSpeculate;
-          }
-          jvmpath[0] = '\0';
-          jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE);
-          /* exec child can do error checking on the existence of the path */
-          jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath,
-                                     ((wanted==64)?BIG_ARCH:SMALL_ARCH));
-
-        }
-      EndDataModelSpeculate: /* give up and let other code report error message */
-        ;
-#else
-        fprintf(stderr, "Running a %d-bit JVM is not supported on this platform.\n", wanted);
-        exit(1);
-#endif
-      }
-
-      /*
-       * We will set the LD_LIBRARY_PATH as follows:
-       *
-       *     o          $JVMPATH (directory portion only)
-       *     o          $JRE/lib/$ARCH
-       *     o          $JRE/../lib/$ARCH
-       *
-       * followed by the user's previous effective LD_LIBRARY_PATH, if
-       * any.
-       */
-
-#ifdef __sun
-      /*
-       * Starting in Solaris 7, ld.so.1 supports three LD_LIBRARY_PATH
-       * variables:
-       *
-       * 1. LD_LIBRARY_PATH -- used for 32 and 64 bit searches if
-       * data-model specific variables are not set.
-       *
-       * 2. LD_LIBRARY_PATH_64 -- overrides and replaces LD_LIBRARY_PATH
-       * for 64-bit binaries.
-       *
-       * 3. LD_LIBRARY_PATH_32 -- overrides and replaces LD_LIBRARY_PATH
-       * for 32-bit binaries.
-       *
-       * The vm uses LD_LIBRARY_PATH to set the java.library.path system
-       * property.  To shield the vm from the complication of multiple
-       * LD_LIBRARY_PATH variables, if the appropriate data model
-       * specific variable is set, we will act as if LD_LIBRARY_PATH had
-       * the value of the data model specific variant and the data model
-       * specific variant will be unset.  Note that the variable for the
-       * *wanted* data model must be used (if it is set), not simply the
-       * current running data model.
-       */
-
-      switch(wanted) {
-      case 0:
-        if(running == 32) {
-          dmpath = getenv("LD_LIBRARY_PATH_32");
-          wanted = 32;
-        }
-        else {
-          dmpath = getenv("LD_LIBRARY_PATH_64");
-          wanted = 64;
-        }
-        break;
-
-      case 32:
-        dmpath = getenv("LD_LIBRARY_PATH_32");
-        break;
-
-      case 64:
-        dmpath = getenv("LD_LIBRARY_PATH_64");
-        break;
-
-      default:
-        fprintf(stderr, "Improper value at line %d.", __LINE__);
-        exit(1); /* unknown value in wanted */
-        break;
-      }
-
-      /*
-       * If dmpath is NULL, the relevant data model specific variable is
-       * not set and normal LD_LIBRARY_PATH should be used.
-       */
-      if( dmpath == NULL) {
-        runpath = getenv("LD_LIBRARY_PATH");
-      }
-      else {
-        runpath = dmpath;
-      }
-#else
-      /*
-       * If not on Solaris, assume only a single LD_LIBRARY_PATH
-       * variable.
-       */
-      runpath = getenv("LD_LIBRARY_PATH");
-#endif /* __sun */
-
-#ifdef __linux
-      /*
-       * On linux, if a binary is running as sgid or suid, glibc sets
-       * LD_LIBRARY_PATH to the empty string for security purposes.  (In
-       * contrast, on Solaris the LD_LIBRARY_PATH variable for a
-       * privileged binary does not lose its settings; but the dynamic
-       * linker does apply more scrutiny to the path.) The launcher uses
-       * the value of LD_LIBRARY_PATH to prevent an exec loop.
-       * Therefore, if we are running sgid or suid, this function's
-       * setting of LD_LIBRARY_PATH will be ineffective and we should
-       * return from the function now.  Getting the right libraries to
-       * be found must be handled through other mechanisms.
-       */
-      if((getgid() != getegid()) || (getuid() != geteuid()) ) {
-        return;
-      }
-#endif
-
-      /* runpath contains current effective LD_LIBRARY_PATH setting */
-
-      jvmpath = strdup(jvmpath);
-      new_runpath = MemAlloc( ((runpath!=NULL)?strlen(runpath):0) +
-                              2*strlen(jrepath) + 2*strlen(arch) +
-                              strlen(jvmpath) + 52);
-      newpath = new_runpath + strlen("LD_LIBRARY_PATH=");
-
-
-      /*
-       * Create desired LD_LIBRARY_PATH value for target data model.
-       */
-      {
-        /* remove the name of the .so from the JVM path */
-        lastslash = strrchr(jvmpath, '/');
-        if (lastslash)
-          *lastslash = '\0';
-
-
-        /* jvmpath, ((running != wanted)?((wanted==64)?"/"BIG_ARCH:"/.."):""), */
-
-        sprintf(new_runpath, "LD_LIBRARY_PATH="
-                "%s:"
-                "%s/lib/%s:"
-                "%s/../lib/%s",
-                jvmpath,
-#ifdef DUAL_MODE
-                jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH),
-                jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH)
-#else
-                jrepath, arch,
-                jrepath, arch
-#endif
-                );
-
-
-        /*
-         * Check to make sure that the prefix of the current path is the
-         * desired environment variable setting.
-         */
-        if (runpath != NULL &&
-            strncmp(newpath, runpath, strlen(newpath))==0 &&
-            (runpath[strlen(newpath)] == 0 || runpath[strlen(newpath)] == ':') &&
-            (running == wanted) /* data model does not have to be changed */
-#ifdef __sun
-            && (dmpath == NULL)    /* data model specific variables not set  */
-#endif
-            ) {
-
-          return;
-
-        }
-      }
-
-      /*
-       * Place the desired environment setting onto the prefix of
-       * LD_LIBRARY_PATH.  Note that this prevents any possible infinite
-       * loop of execv() because we test for the prefix, above.
-       */
-      if (runpath != 0) {
-        strcat(new_runpath, ":");
-        strcat(new_runpath, runpath);
-      }
-
-      if( putenv(new_runpath) != 0) {
-        exit(1); /* problem allocating memory; LD_LIBRARY_PATH not set
-                    properly */
-      }
-
-      /*
-       * Unix systems document that they look at LD_LIBRARY_PATH only
-       * once at startup, so we have to re-exec the current executable
-       * to get the changed environment variable to have an effect.
-       */
-
-#ifdef __sun
-      /*
-       * If dmpath is not NULL, remove the data model specific string
-       * in the environment for the exec'ed child.
-       */
-
-      if( dmpath != NULL)
-        (void)UnsetEnv((wanted==32)?"LD_LIBRARY_PATH_32":"LD_LIBRARY_PATH_64");
-#endif
-
-      newenvp = environ;
-
-      {
-        char *newexec = execname;
-#ifdef DUAL_MODE
-        /*
-         * If the data model is being changed, the path to the
-         * executable must be updated accordingly; the executable name
-         * and directory the executable resides in are separate.  In the
-         * case of 32 => 64, the new bits are assumed to reside in, e.g.
-         * "olddir/BIGARCH/execname"; in the case of 64 => 32,
-         * the bits are assumed to be in "olddir/../execname".  For example,
-         *
-         * olddir/sparcv9/execname
-         * olddir/amd64/execname
-         *
-         * for Solaris SPARC and Linux amd64, respectively.
-         */
-
-        if (running != wanted) {
-          char *oldexec = strcpy(MemAlloc(strlen(execname) + 1), execname);
-          char *olddir = oldexec;
-          char *oldbase = strrchr(oldexec, '/');
-
-
-          newexec = MemAlloc(strlen(execname) + 20);
-          *oldbase++ = 0;
-          sprintf(newexec, "%s/%s/%s", olddir,
-                  ((wanted==64) ? BIG_ARCH : ".."), oldbase);
-          argv[0] = newexec;
-        }
-#endif
-
-        execve(newexec, argv, newenvp);
-        perror("execve()");
-
-        fprintf(stderr, "Error trying to exec %s.\n", newexec);
-        fprintf(stderr, "Check if file exists and permissions are set correctly.\n");
-
-#ifdef DUAL_MODE
-        if (running != wanted) {
-          fprintf(stderr, "Failed to start a %d-bit JVM process from a %d-bit JVM.\n",
-                  wanted, running);
-#  ifdef __sun
-
-#    ifdef __sparc
-          fprintf(stderr, "Verify all necessary J2SE components have been installed.\n" );
-          fprintf(stderr,
-                  "(Solaris SPARC 64-bit components must be installed after 32-bit components.)\n" );
-#    else
-          fprintf(stderr, "Either 64-bit processes are not supported by this platform\n");
-          fprintf(stderr, "or the 64-bit components have not been installed.\n");
-#    endif
-        }
-#  endif
-#endif
-
-      }
-
-      exit(1);
-    }
-
-#else  /* ifndef GAMMA */
-
-  /* gamma launcher is simpler in that it doesn't handle VM flavors, data  */
-  /* model, LD_LIBRARY_PATH, etc. Assuming everything is set-up correctly  */
-  /* all we need to do here is to return correct path names. See also      */
-  /* GetJVMPath() and GetApplicationHome().                                */
-
-  { char *arch = (char *)GetArch(); /* like sparc or sparcv9 */
-    char *p;
-
-    if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) {
-      fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n");
-      exit(2);
-    }
-
-    if (!GetJVMPath(jrepath, NULL, jvmpath, so_jvmpath, arch )) {
-      fprintf(stderr, "Error: no JVM at `%s'.\n", jvmpath);
-      exit(4);
-    }
-  }
-
-#endif  /* ifndef GAMMA */
-}
-
-
-/*
- * On Solaris VM choosing is done by the launcher (java.c).
- */
-static jboolean
-GetJVMPath(const char *jrepath, const char *jvmtype,
-           char *jvmpath, jint jvmpathsize, char * arch)
-{
-    struct stat s;
-
-#ifndef GAMMA
-    if (strchr(jvmtype, '/')) {
-        sprintf(jvmpath, "%s/" JVM_DLL, jvmtype);
-    } else {
-        sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
-    }
-#else
-    /* For gamma launcher, JVM is either built-in or in the same directory. */
-    /* Either way we return "<exe_path>/libjvm.so" where <exe_path> is the  */
-    /* directory where gamma launcher is located.                           */
-
-    char *p;
-
-    snprintf(jvmpath, jvmpathsize, "%s", GetExecname());
-    p = strrchr(jvmpath, '/');
-    if (p) {
-       /* replace executable name with libjvm.so */
-       snprintf(p + 1, jvmpathsize - (p + 1 - jvmpath), "%s", JVM_DLL);
-    } else {
-       /* this case shouldn't happen */
-       snprintf(jvmpath, jvmpathsize, "%s", JVM_DLL);
-    }
-#endif
-
-    if (_launcher_debug)
-      printf("Does `%s' exist ... ", jvmpath);
-
-    if (stat(jvmpath, &s) == 0) {
-        if (_launcher_debug)
-          printf("yes.\n");
-        return JNI_TRUE;
-    } else {
-        if (_launcher_debug)
-          printf("no.\n");
-        return JNI_FALSE;
-    }
-}
-
-/*
- * Find path to JRE based on .exe's location or registry settings.
- */
-static jboolean
-GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative)
-{
-    char libjava[MAXPATHLEN];
-
-    if (GetApplicationHome(path, pathsize)) {
-        /* Is JRE co-located with the application? */
-        sprintf(libjava, "%s/lib/%s/" JAVA_DLL, path, arch);
-        if (access(libjava, F_OK) == 0) {
-            goto found;
-        }
-
-        /* Does the app ship a private JRE in <apphome>/jre directory? */
-        sprintf(libjava, "%s/jre/lib/%s/" JAVA_DLL, path, arch);
-        if (access(libjava, F_OK) == 0) {
-            strcat(path, "/jre");
-            goto found;
-        }
-    }
-
-    if (!speculative)
-      fprintf(stderr, "Error: could not find " JAVA_DLL "\n");
-    return JNI_FALSE;
-
- found:
-    if (_launcher_debug)
-      printf("JRE path is %s\n", path);
-    return JNI_TRUE;
-}
-
-jboolean
-LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
-{
-#ifdef GAMMA
-    /* JVM is directly linked with gamma launcher; no dlopen() */
-    ifn->CreateJavaVM = JNI_CreateJavaVM;
-    ifn->GetDefaultJavaVMInitArgs = JNI_GetDefaultJavaVMInitArgs;
-    return JNI_TRUE;
-#else
-    Dl_info dlinfo;
-    void *libjvm;
-
-    if (_launcher_debug) {
-        printf("JVM path is %s\n", jvmpath);
-    }
-
-    libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
-    if (libjvm == NULL) {
-#if defined(__sparc) && !defined(_LP64) /* i.e. 32-bit sparc */
-      FILE * fp;
-      Elf32_Ehdr elf_head;
-      int count;
-      int location;
-
-      fp = fopen(jvmpath, "r");
-      if(fp == NULL)
-        goto error;
-
-      /* read in elf header */
-      count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp);
-      fclose(fp);
-      if(count < 1)
-        goto error;
-
-      /*
-       * Check for running a server vm (compiled with -xarch=v8plus)
-       * on a stock v8 processor.  In this case, the machine type in
-       * the elf header would not be included the architecture list
-       * provided by the isalist command, which is turn is gotten from
-       * sysinfo.  This case cannot occur on 64-bit hardware and thus
-       * does not have to be checked for in binaries with an LP64 data
-       * model.
-       */
-      if(elf_head.e_machine == EM_SPARC32PLUS) {
-        char buf[257];  /* recommended buffer size from sysinfo man
-                           page */
-        long length;
-        char* location;
-
-        length = sysinfo(SI_ISALIST, buf, 257);
-        if(length > 0) {
-          location = strstr(buf, "sparcv8plus ");
-          if(location == NULL) {
-            fprintf(stderr, "SPARC V8 processor detected; Server compiler requires V9 or better.\n");
-            fprintf(stderr, "Use Client compiler on V8 processors.\n");
-            fprintf(stderr, "Could not create the Java virtual machine.\n");
-            return JNI_FALSE;
-          }
-        }
-      }
-#endif
-      fprintf(stderr, "dl failure on line %d", __LINE__);
-      goto error;
-    }
-
-    ifn->CreateJavaVM = (CreateJavaVM_t)
-      dlsym(libjvm, "JNI_CreateJavaVM");
-    if (ifn->CreateJavaVM == NULL)
-        goto error;
-
-    ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
-        dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");
-    if (ifn->GetDefaultJavaVMInitArgs == NULL)
-      goto error;
-
-    return JNI_TRUE;
-
-error:
-    fprintf(stderr, "Error: failed %s, because %s\n", jvmpath, dlerror());
-    return JNI_FALSE;
-#endif /* GAMMA */
-}
-
-/*
- * Get the path to the file that has the usage message for -X options.
- */
-void
-GetXUsagePath(char *buf, jint bufsize)
-{
-    static const char Xusage_txt[] = "/Xusage.txt";
-    Dl_info dlinfo;
-
-    /* we use RTLD_NOW because of problems with ld.so.1 and green threads */
-    dladdr(dlsym(dlopen(JVM_DLL, RTLD_NOW), "JNI_CreateJavaVM"), &dlinfo);
-    strncpy(buf, (char *)dlinfo.dli_fname, bufsize - sizeof(Xusage_txt));
-
-    buf[bufsize-1] = '\0';
-    strcpy(strrchr(buf, '/'), Xusage_txt);
-}
-
-/*
- * If app is "/foo/bin/javac", or "/foo/bin/sparcv9/javac" then put
- * "/foo" into buf.
- */
-jboolean
-GetApplicationHome(char *buf, jint bufsize)
-{
-#ifdef __linux__
-    char *execname = GetExecname();
-    if (execname) {
-        strncpy(buf, execname, bufsize-1);
-        buf[bufsize-1] = '\0';
-    } else {
-        return JNI_FALSE;
-    }
-#else
-    Dl_info dlinfo;
-
-    dladdr((void *)GetApplicationHome, &dlinfo);
-    if (realpath(dlinfo.dli_fname, buf) == NULL) {
-        fprintf(stderr, "Error: realpath(`%s') failed.\n", dlinfo.dli_fname);
-        return JNI_FALSE;
-    }
-#endif
-
-#ifdef GAMMA
-    {
-      /* gamma launcher uses JAVA_HOME environment variable to find JDK/JRE */
-      char* java_home_var = getenv("JAVA_HOME");
-      if (java_home_var == NULL) {
-        printf("JAVA_HOME must point to a valid JDK/JRE to run gamma\n");
-        return JNI_FALSE;
-      }
-      snprintf(buf, bufsize, "%s", java_home_var);
-    }
-#else
-    if (strrchr(buf, '/') == 0) {
-        buf[0] = '\0';
-        return JNI_FALSE;
-    }
-    *(strrchr(buf, '/')) = '\0';        /* executable file      */
-    if (strlen(buf) < 4 || strrchr(buf, '/') == 0) {
-        buf[0] = '\0';
-        return JNI_FALSE;
-    }
-    if (strcmp("/bin", buf + strlen(buf) - 4) != 0)
-        *(strrchr(buf, '/')) = '\0';    /* sparcv9 or amd64     */
-    if (strlen(buf) < 4 || strcmp("/bin", buf + strlen(buf) - 4) != 0) {
-        buf[0] = '\0';
-        return JNI_FALSE;
-    }
-    *(strrchr(buf, '/')) = '\0';        /* bin                  */
-#endif /* GAMMA */
-
-    return JNI_TRUE;
-}
-
-
-/*
- * Return true if the named program exists
- */
-static int
-ProgramExists(char *name)
-{
-    struct stat sb;
-    if (stat(name, &sb) != 0) return 0;
-    if (S_ISDIR(sb.st_mode)) return 0;
-    return (sb.st_mode & S_IEXEC) != 0;
-}
-
-
-/*
- * Find a command in a directory, returning the path.
- */
-static char *
-Resolve(char *indir, char *cmd)
-{
-    char name[PATH_MAX + 2], *real;
-
-    if ((strlen(indir) + strlen(cmd) + 1)  > PATH_MAX) return 0;
-    sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd);
-    if (!ProgramExists(name)) return 0;
-    real = MemAlloc(PATH_MAX + 2);
-    if (!realpath(name, real))
-        strcpy(real, name);
-    return real;
-}
-
-
-/*
- * Find a path for the executable
- */
-static char *
-FindExecName(char *program)
-{
-    char cwdbuf[PATH_MAX+2];
-    char *path;
-    char *tmp_path;
-    char *f;
-    char *result = NULL;
-
-    /* absolute path? */
-    if (*program == FILE_SEPARATOR ||
-        (FILE_SEPARATOR=='\\' && strrchr(program, ':')))
-        return Resolve("", program+1);
-
-    /* relative path? */
-    if (strrchr(program, FILE_SEPARATOR) != 0) {
-        char buf[PATH_MAX+2];
-        return Resolve(getcwd(cwdbuf, sizeof(cwdbuf)), program);
-    }
-
-    /* from search path? */
-    path = getenv("PATH");
-    if (!path || !*path) path = ".";
-    tmp_path = MemAlloc(strlen(path) + 2);
-    strcpy(tmp_path, path);
-
-    for (f=tmp_path; *f && result==0; ) {
-        char *s = f;
-        while (*f && (*f != PATH_SEPARATOR)) ++f;
-        if (*f) *f++ = 0;
-        if (*s == FILE_SEPARATOR)
-            result = Resolve(s, program);
-        else {
-            /* relative path element */
-            char dir[2*PATH_MAX];
-            sprintf(dir, "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)),
-                    FILE_SEPARATOR, s);
-            result = Resolve(dir, program);
-        }
-        if (result != 0) break;
-    }
-
-    free(tmp_path);
-    return result;
-}
-
-
-/* Store the name of the executable once computed */
-static char *execname = NULL;
-
-/*
- * Compute the name of the executable
- *
- * In order to re-exec securely we need the absolute path of the
- * executable. On Solaris getexecname(3c) may not return an absolute
- * path so we use dladdr to get the filename of the executable and
- * then use realpath to derive an absolute path. From Solaris 9
- * onwards the filename returned in DL_info structure from dladdr is
- * an absolute pathname so technically realpath isn't required.
- * On Linux we read the executable name from /proc/self/exe.
- * As a fallback, and for platforms other than Solaris and Linux,
- * we use FindExecName to compute the executable name.
- */
-static char *
-SetExecname(char **argv)
-{
-    char* exec_path = NULL;
-
-    if (execname != NULL)       /* Already determined */
-        return (execname);
-
-#if defined(__sun)
-    {
-        Dl_info dlinfo;
-        if (dladdr((void*)&SetExecname, &dlinfo)) {
-            char *resolved = (char*)MemAlloc(PATH_MAX+1);
-            if (resolved != NULL) {
-                exec_path = realpath(dlinfo.dli_fname, resolved);
-                if (exec_path == NULL) {
-                    free(resolved);
-                }
-            }
-        }
-    }
-#elif defined(__linux__)
-    {
-        const char* self = "/proc/self/exe";
-        char buf[PATH_MAX+1];
-        int len = readlink(self, buf, PATH_MAX);
-        if (len >= 0) {
-            buf[len] = '\0';            /* readlink doesn't nul terminate */
-            exec_path = strdup(buf);
-        }
-    }
-#else /* !__sun && !__linux */
-    {
-        /* Not implemented */
-    }
-#endif
-
-    if (exec_path == NULL) {
-        exec_path = FindExecName(argv[0]);
-    }
-    execname = exec_path;
-    return exec_path;
-}
-
-/*
- * Return the name of the executable.  Used in java_md.c to find the JRE area.
- */
-static char *
-GetExecname() {
-  return execname;
-}
-
-void ReportErrorMessage(char * message, jboolean always) {
-  if (always) {
-    fprintf(stderr, "%s\n", message);
-  }
-}
-
-void ReportErrorMessage2(char * format, char * string, jboolean always) {
-  if (always) {
-    fprintf(stderr, format, string);
-    fprintf(stderr, "\n");
-  }
-}
-
-void  ReportExceptionDescription(JNIEnv * env) {
-  (*env)->ExceptionDescribe(env);
-}
-
-/*
- * Return JNI_TRUE for an option string that has no effect but should
- * _not_ be passed on to the vm; return JNI_FALSE otherwise.  On
- * Solaris SPARC, this screening needs to be done if:
- * 1) LD_LIBRARY_PATH does _not_ need to be reset and
- * 2) -d32 or -d64 is passed to a binary with a matching data model
- *    (the exec in SetLibraryPath removes -d<n> options and points the
- *    exec to the proper binary).  When this exec is not done, these options
- *    would end up getting passed onto the vm.
- */
-jboolean RemovableMachineDependentOption(char * option) {
-  /*
-   * Unconditionally remove both -d32 and -d64 options since only
-   * the last such options has an effect; e.g.
-   * java -d32 -d64 -d32 -version
-   * is equivalent to
-   * java -d32 -version
-   */
-
-  if( (strcmp(option, "-d32")  == 0 ) ||
-      (strcmp(option, "-d64")  == 0 ))
-    return JNI_TRUE;
-  else
-    return JNI_FALSE;
-}
-
-void PrintMachineDependentOptions() {
-      fprintf(stdout,
-        "    -d32          use a 32-bit data model if available\n"
-        "\n"
-        "    -d64          use a 64-bit data model if available\n");
-      return;
-}
-
-#ifndef GAMMA  /* gamma launcher does not have ergonomics */
-
-/*
- * The following methods (down to ServerClassMachine()) answer
- * the question about whether a machine is a "server-class"
- * machine.  A server-class machine is loosely defined as one
- * with 2 or more processors and 2 gigabytes or more physical
- * memory.  The definition of a processor is a physical package,
- * not a hyperthreaded chip masquerading as a multi-processor.
- * The definition of memory is also somewhat fuzzy, since x86
- * machines seem not to report all the memory in their DIMMs, we
- * think because of memory mapping of graphics cards, etc.
- *
- * This code is somewhat more confused with #ifdef's than we'd
- * like because this file is used by both Solaris and Linux
- * platforms, and so needs to be parameterized for SPARC and
- * i586 hardware.  The other Linux platforms (amd64 and ia64)
- * don't even ask this question, because they only come with
- * server JVMs.  */
-
-# define KB (1024UL)
-# define MB (1024UL * KB)
-# define GB (1024UL * MB)
-
-/* Compute physical memory by asking the OS */
-uint64_t
-physical_memory(void) {
-  const uint64_t pages     = (uint64_t) sysconf(_SC_PHYS_PAGES);
-  const uint64_t page_size = (uint64_t) sysconf(_SC_PAGESIZE);
-  const uint64_t result    = pages * page_size;
-# define UINT64_FORMAT "%" PRIu64
-
-  if (_launcher_debug) {
-    printf("pages: " UINT64_FORMAT
-           "  page_size: " UINT64_FORMAT
-           "  physical memory: " UINT64_FORMAT " (%.3fGB)\n",
-           pages, page_size, result, result / (double) GB);
-  }
-  return result;
-}
-
-#if defined(__sun) && defined(__sparc)
-
-/* Methods for solaris-sparc: these are easy. */
-
-/* Ask the OS how many processors there are. */
-unsigned long
-physical_processors(void) {
-  const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
-
-  if (_launcher_debug) {
-    printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
-  }
-  return sys_processors;
-}
-
-/* The solaris-sparc version of the "server-class" predicate. */
-jboolean
-solaris_sparc_ServerClassMachine(void) {
-  jboolean            result            = JNI_FALSE;
-  /* How big is a server class machine? */
-  const unsigned long server_processors = 2UL;
-  const uint64_t      server_memory     = 2UL * GB;
-  const uint64_t      actual_memory     = physical_memory();
-
-  /* Is this a server class machine? */
-  if (actual_memory >= server_memory) {
-    const unsigned long actual_processors = physical_processors();
-    if (actual_processors >= server_processors) {
-      result = JNI_TRUE;
-    }
-  }
-  if (_launcher_debug) {
-    printf("solaris_" ARCH "_ServerClassMachine: %s\n",
-           (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE"));
-  }
-  return result;
-}
-
-#endif /* __sun && __sparc */
-
-#if defined(__sun) && defined(i586)
-
-/*
- * A utility method for asking the CPU about itself.
- * There's a corresponding version of linux-i586
- * because the compilers are different.
- */
-void
-get_cpuid(uint32_t arg,
-          uint32_t* eaxp,
-          uint32_t* ebxp,
-          uint32_t* ecxp,
-          uint32_t* edxp) {
-#ifdef _LP64
-  asm(
-  /* rbx is a callee-saved register */
-      " movq    %rbx, %r11  \n"
-  /* rdx and rcx are 3rd and 4th argument registers */
-      " movq    %rdx, %r10  \n"
-      " movq    %rcx, %r9   \n"
-      " movl    %edi, %eax  \n"
-      " cpuid               \n"
-      " movl    %eax, (%rsi)\n"
-      " movl    %ebx, (%r10)\n"
-      " movl    %ecx, (%r9) \n"
-      " movl    %edx, (%r8) \n"
-  /* Restore rbx */
-      " movq    %r11, %rbx");
-#else
-  /* EBX is a callee-saved register */
-  asm(" pushl   %ebx");
-  /* Need ESI for storing through arguments */
-  asm(" pushl   %esi");
-  asm(" movl    8(%ebp), %eax   \n"
-      " cpuid                   \n"
-      " movl    12(%ebp), %esi  \n"
-      " movl    %eax, (%esi)    \n"
-      " movl    16(%ebp), %esi  \n"
-      " movl    %ebx, (%esi)    \n"
-      " movl    20(%ebp), %esi  \n"
-      " movl    %ecx, (%esi)    \n"
-      " movl    24(%ebp), %esi  \n"
-      " movl    %edx, (%esi)      ");
-  /* Restore ESI and EBX */
-  asm(" popl    %esi");
-  /* Restore EBX */
-  asm(" popl    %ebx");
-#endif
-}
-
-#endif /* __sun && i586 */
-
-#if defined(__linux__) && defined(i586)
-
-/*
- * A utility method for asking the CPU about itself.
- * There's a corresponding version of solaris-i586
- * because the compilers are different.
- */
-void
-get_cpuid(uint32_t arg,
-          uint32_t* eaxp,
-          uint32_t* ebxp,
-          uint32_t* ecxp,
-          uint32_t* edxp) {
-#ifdef _LP64
-  __asm__ volatile (/* Instructions */
-                    "   movl    %4, %%eax  \n"
-                    "   cpuid              \n"
-                    "   movl    %%eax, (%0)\n"
-                    "   movl    %%ebx, (%1)\n"
-                    "   movl    %%ecx, (%2)\n"
-                    "   movl    %%edx, (%3)\n"
-                    : /* Outputs */
-                    : /* Inputs */
-                    "r" (eaxp),
-                    "r" (ebxp),
-                    "r" (ecxp),
-                    "r" (edxp),
-                    "r" (arg)
-                    : /* Clobbers */
-                    "%rax", "%rbx", "%rcx", "%rdx", "memory"
-                    );
-#else
-  uint32_t value_of_eax = 0;
-  uint32_t value_of_ebx = 0;
-  uint32_t value_of_ecx = 0;
-  uint32_t value_of_edx = 0;
-  __asm__ volatile (/* Instructions */
-                        /* ebx is callee-save, so push it */
-                        /* even though it's in the clobbers section */
-                    "   pushl   %%ebx      \n"
-                    "   movl    %4, %%eax  \n"
-                    "   cpuid              \n"
-                    "   movl    %%eax, %0  \n"
-                    "   movl    %%ebx, %1  \n"
-                    "   movl    %%ecx, %2  \n"
-                    "   movl    %%edx, %3  \n"
-                        /* restore ebx */
-                    "   popl    %%ebx      \n"
-
-                    : /* Outputs */
-                    "=m" (value_of_eax),
-                    "=m" (value_of_ebx),
-                    "=m" (value_of_ecx),
-                    "=m" (value_of_edx)
-                    : /* Inputs */
-                    "m" (arg)
-                    : /* Clobbers */
-                    "%eax", "%ebx", "%ecx", "%edx"
-                    );
-  *eaxp = value_of_eax;
-  *ebxp = value_of_ebx;
-  *ecxp = value_of_ecx;
-  *edxp = value_of_edx;
-#endif
-}
-
-#endif /* __linux__ && i586 */
-
-#ifdef i586
-/*
- * Routines shared by solaris-i586 and linux-i586.
- */
-
-enum HyperThreadingSupport_enum {
-  hts_supported        =  1,
-  hts_too_soon_to_tell =  0,
-  hts_not_supported    = -1,
-  hts_not_pentium4     = -2,
-  hts_not_intel        = -3
-};
-typedef enum HyperThreadingSupport_enum HyperThreadingSupport;
-
-/* Determine if hyperthreading is supported */
-HyperThreadingSupport
-hyperthreading_support(void) {
-  HyperThreadingSupport result = hts_too_soon_to_tell;
-  /* Bits 11 through 8 is family processor id */
-# define FAMILY_ID_SHIFT 8
-# define FAMILY_ID_MASK 0xf
-  /* Bits 23 through 20 is extended family processor id */
-# define EXT_FAMILY_ID_SHIFT 20
-# define EXT_FAMILY_ID_MASK 0xf
-  /* Pentium 4 family processor id */
-# define PENTIUM4_FAMILY_ID 0xf
-  /* Bit 28 indicates Hyper-Threading Technology support */
-# define HT_BIT_SHIFT 28
-# define HT_BIT_MASK 1
-  uint32_t vendor_id[3] = { 0U, 0U, 0U };
-  uint32_t value_of_eax = 0U;
-  uint32_t value_of_edx = 0U;
-  uint32_t dummy        = 0U;
-
-  /* Yes, this is supposed to be [0], [2], [1] */
-  get_cpuid(0, &dummy, &vendor_id[0], &vendor_id[2], &vendor_id[1]);
-  if (_launcher_debug) {
-    printf("vendor: %c %c %c %c %c %c %c %c %c %c %c %c \n",
-           ((vendor_id[0] >>  0) & 0xff),
-           ((vendor_id[0] >>  8) & 0xff),
-           ((vendor_id[0] >> 16) & 0xff),
-           ((vendor_id[0] >> 24) & 0xff),
-           ((vendor_id[1] >>  0) & 0xff),
-           ((vendor_id[1] >>  8) & 0xff),
-           ((vendor_id[1] >> 16) & 0xff),
-           ((vendor_id[1] >> 24) & 0xff),
-           ((vendor_id[2] >>  0) & 0xff),
-           ((vendor_id[2] >>  8) & 0xff),
-           ((vendor_id[2] >> 16) & 0xff),
-           ((vendor_id[2] >> 24) & 0xff));
-  }
-  get_cpuid(1, &value_of_eax, &dummy, &dummy, &value_of_edx);
-  if (_launcher_debug) {
-    printf("value_of_eax: 0x%x  value_of_edx: 0x%x\n",
-           value_of_eax, value_of_edx);
-  }
-  if ((((value_of_eax >> FAMILY_ID_SHIFT) & FAMILY_ID_MASK) == PENTIUM4_FAMILY_ID) ||
-      (((value_of_eax >> EXT_FAMILY_ID_SHIFT) & EXT_FAMILY_ID_MASK) != 0)) {
-    if ((((vendor_id[0] >>  0) & 0xff) == 'G') &&
-        (((vendor_id[0] >>  8) & 0xff) == 'e') &&
-        (((vendor_id[0] >> 16) & 0xff) == 'n') &&
-        (((vendor_id[0] >> 24) & 0xff) == 'u') &&
-        (((vendor_id[1] >>  0) & 0xff) == 'i') &&
-        (((vendor_id[1] >>  8) & 0xff) == 'n') &&
-        (((vendor_id[1] >> 16) & 0xff) == 'e') &&
-        (((vendor_id[1] >> 24) & 0xff) == 'I') &&
-        (((vendor_id[2] >>  0) & 0xff) == 'n') &&
-        (((vendor_id[2] >>  8) & 0xff) == 't') &&
-        (((vendor_id[2] >> 16) & 0xff) == 'e') &&
-        (((vendor_id[2] >> 24) & 0xff) == 'l')) {
-      if (((value_of_edx >> HT_BIT_SHIFT) & HT_BIT_MASK) == HT_BIT_MASK) {
-        if (_launcher_debug) {
-          printf("Hyperthreading supported\n");
-        }
-        result = hts_supported;
-      } else {
-        if (_launcher_debug) {
-          printf("Hyperthreading not supported\n");
-        }
-        result = hts_not_supported;
-      }
-    } else {
-      if (_launcher_debug) {
-        printf("Not GenuineIntel\n");
-      }
-      result = hts_not_intel;
-    }
-  } else {
-    if (_launcher_debug) {
-      printf("not Pentium 4 or extended\n");
-    }
-    result = hts_not_pentium4;
-  }
-  return result;
-}
-
-/* Determine how many logical processors there are per CPU */
-unsigned int
-logical_processors_per_package(void) {
-  /*
-   * After CPUID with EAX==1, register EBX bits 23 through 16
-   * indicate the number of logical processors per package
-   */
-# define NUM_LOGICAL_SHIFT 16
-# define NUM_LOGICAL_MASK 0xff
-  unsigned int result                        = 1U;
-  const HyperThreadingSupport hyperthreading = hyperthreading_support();
-
-  if (hyperthreading == hts_supported) {
-    uint32_t value_of_ebx = 0U;
-    uint32_t dummy        = 0U;
-
-    get_cpuid(1, &dummy, &value_of_ebx, &dummy, &dummy);
-    result = (value_of_ebx >> NUM_LOGICAL_SHIFT) & NUM_LOGICAL_MASK;
-    if (_launcher_debug) {
-      printf("logical processors per package: %u\n", result);
-    }
-  }
-  return result;
-}
-
-/* Compute the number of physical processors, not logical processors */
-unsigned long
-physical_processors(void) {
-  const long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
-  unsigned long result      = sys_processors;
-
-  if (_launcher_debug) {
-    printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
-  }
-  if (sys_processors > 1) {
-    unsigned int logical_processors = logical_processors_per_package();
-    if (logical_processors > 1) {
-      result = (unsigned long) sys_processors / logical_processors;
-    }
-  }
-  if (_launcher_debug) {
-    printf("physical processors: %lu\n", result);
-  }
-  return result;
-}
-
-#endif /* i586 */
-
-#if defined(__sun) && defined(i586)
-
-/* The definition of a server-class machine for solaris-i586/amd64 */
-jboolean
-solaris_i586_ServerClassMachine(void) {
-  jboolean            result            = JNI_FALSE;
-  /* How big is a server class machine? */
-  const unsigned long server_processors = 2UL;
-  const uint64_t      server_memory     = 2UL * GB;
-  /*
-   * We seem not to get our full complement of memory.
-   *     We allow some part (1/8?) of the memory to be "missing",
-   *     based on the sizes of DIMMs, and maybe graphics cards.
-   */
-  const uint64_t      missing_memory    = 256UL * MB;
-  const uint64_t      actual_memory     = physical_memory();
-
-  /* Is this a server class machine? */
-  if (actual_memory >= (server_memory - missing_memory)) {
-    const unsigned long actual_processors = physical_processors();
-    if (actual_processors >= server_processors) {
-      result = JNI_TRUE;
-    }
-  }
-  if (_launcher_debug) {
-    printf("solaris_" ARCH "_ServerClassMachine: %s\n",
-           (result == JNI_TRUE ? "true" : "false"));
-  }
-  return result;
-}
-
-#endif /* __sun && i586 */
-
-#if defined(__linux__) && defined(i586)
-
-/* The definition of a server-class machine for linux-i586 */
-jboolean
-linux_i586_ServerClassMachine(void) {
-  jboolean            result            = JNI_FALSE;
-  /* How big is a server class machine? */
-  const unsigned long server_processors = 2UL;
-  const uint64_t      server_memory     = 2UL * GB;
-  /*
-   * We seem not to get our full complement of memory.
-   *     We allow some part (1/8?) of the memory to be "missing",
-   *     based on the sizes of DIMMs, and maybe graphics cards.
-   */
-  const uint64_t      missing_memory    = 256UL * MB;
-  const uint64_t      actual_memory     = physical_memory();
-
-  /* Is this a server class machine? */
-  if (actual_memory >= (server_memory - missing_memory)) {
-    const unsigned long actual_processors = physical_processors();
-    if (actual_processors >= server_processors) {
-      result = JNI_TRUE;
-    }
-  }
-  if (_launcher_debug) {
-    printf("linux_" ARCH "_ServerClassMachine: %s\n",
-           (result == JNI_TRUE ? "true" : "false"));
-  }
-  return result;
-}
-
-#endif /* __linux__ && i586 */
-
-/* Dispatch to the platform-specific definition of "server-class" */
-jboolean
-ServerClassMachine(void) {
-  jboolean result = JNI_FALSE;
-#if   defined(__sun) && defined(__sparc)
-  result = solaris_sparc_ServerClassMachine();
-#elif defined(__sun) && defined(i586)
-  result = solaris_i586_ServerClassMachine();
-#elif defined(__linux__) && defined(i586)
-  result = linux_i586_ServerClassMachine();
-#else
-  if (_launcher_debug) {
-    printf("ServerClassMachine: returns default value of %s\n",
-           (result == JNI_TRUE ? "true" : "false"));
-  }
-#endif
-  return result;
-}
-
-#endif /* ifndef GAMMA */
-
-#ifndef GAMMA /* gamma launcher does not choose JDK/JRE/JVM */
-
-/*
- *      Since using the file system as a registry is a bit risky, perform
- *      additional sanity checks on the identified directory to validate
- *      it as a valid jre/sdk.
- *
- *      Return 0 if the tests fail; otherwise return non-zero (true).
- *
- *      Note that checking for anything more than the existence of an
- *      executable object at bin/java relative to the path being checked
- *      will break the regression tests.
- */
-static int
-CheckSanity(char *path, char *dir)
-{
-    char    buffer[PATH_MAX];
-
-    if (strlen(path) + strlen(dir) + 11 > PATH_MAX)
-        return (0);     /* Silently reject "impossibly" long paths */
-
-    (void)strcat(strcat(strcat(strcpy(buffer, path), "/"), dir), "/bin/java");
-    return ((access(buffer, X_OK) == 0) ? 1 : 0);
-}
-
-/*
- *      Determine if there is an acceptable JRE in the directory dirname.
- *      Upon locating the "best" one, return a fully qualified path to
- *      it. "Best" is defined as the most advanced JRE meeting the
- *      constraints contained in the manifest_info. If no JRE in this
- *      directory meets the constraints, return NULL.
- *
- *      Note that we don't check for errors in reading the directory
- *      (which would be done by checking errno).  This is because it
- *      doesn't matter if we get an error reading the directory, or
- *      we just don't find anything interesting in the directory.  We
- *      just return NULL in either case.
- *
- *      The historical names of j2sdk and j2re were changed to jdk and
- *      jre respecively as part of the 1.5 rebranding effort.  Since the
- *      former names are legacy on Linux, they must be recognized for
- *      all time.  Fortunately, this is a minor cost.
- */
-static char
-*ProcessDir(manifest_info *info, char *dirname)
-{
-    DIR     *dirp;
-    struct dirent *dp;
-    char    *best = NULL;
-    int     offset;
-    int     best_offset = 0;
-    char    *ret_str = NULL;
-    char    buffer[PATH_MAX];
-
-    if ((dirp = opendir(dirname)) == NULL)
-        return (NULL);
-
-    do {
-        if ((dp = readdir(dirp)) != NULL) {
-            offset = 0;
-            if ((strncmp(dp->d_name, "jre", 3) == 0) ||
-                (strncmp(dp->d_name, "jdk", 3) == 0))
-                offset = 3;
-            else if (strncmp(dp->d_name, "j2re", 4) == 0)
-                offset = 4;
-            else if (strncmp(dp->d_name, "j2sdk", 5) == 0)
-                offset = 5;
-            if (offset > 0) {
-                if ((acceptable_release(dp->d_name + offset,
-                    info->jre_version)) && CheckSanity(dirname, dp->d_name))
-                    if ((best == NULL) || (exact_version_id(
-                      dp->d_name + offset, best + best_offset) > 0)) {
-                        if (best != NULL)
-                            free(best);
-                        best = strdup(dp->d_name);
-                        best_offset = offset;
-                    }
-            }
-        }
-    } while (dp != NULL);
-    (void) closedir(dirp);
-    if (best == NULL)
-        return (NULL);
-    else {
-        ret_str = MemAlloc(strlen(dirname) + strlen(best) + 2);
-        ret_str = strcat(strcat(strcpy(ret_str, dirname), "/"), best);
-        free(best);
-        return (ret_str);
-    }
-}
-
-/*
- *      This is the global entry point. It examines the host for the optimal
- *      JRE to be used by scanning a set of directories.  The set of directories
- *      is platform dependent and can be overridden by the environment
- *      variable JAVA_VERSION_PATH.
- *
- *      This routine itself simply determines the set of appropriate
- *      directories before passing control onto ProcessDir().
- */
-char*
-LocateJRE(manifest_info* info)
-{
-    char        *path;
-    char        *home;
-    char        *target = NULL;
-    char        *dp;
-    char        *cp;
-
-    /*
-     * Start by getting JAVA_VERSION_PATH
-     */
-    if (info->jre_restrict_search)
-        path = strdup(system_dir);
-    else if ((path = getenv("JAVA_VERSION_PATH")) != NULL)
-        path = strdup(path);
-    else
-        if ((home = getenv("HOME")) != NULL) {
-            path = (char *)MemAlloc(strlen(home) + 13);
-            path = strcat(strcat(strcat(strcpy(path, home),
-                user_dir), ":"), system_dir);
-        } else
-            path = strdup(system_dir);
-
-    /*
-     * Step through each directory on the path. Terminate the scan with
-     * the first directory with an acceptable JRE.
-     */
-    cp = dp = path;
-    while (dp != NULL) {
-        cp = strchr(dp, (int)':');
-        if (cp != NULL)
-            *cp = (char)NULL;
-        if ((target = ProcessDir(info, dp)) != NULL)
-            break;
-        dp = cp;
-        if (dp != NULL)
-            dp++;
-    }
-    free(path);
-    return (target);
-}
-
-/*
- * Given a path to a jre to execute, this routine checks if this process
- * is indeed that jre.  If not, it exec's that jre.
- *
- * We want to actually check the paths rather than just the version string
- * built into the executable, so that given version specification (and
- * JAVA_VERSION_PATH) will yield the exact same Java environment, regardless
- * of the version of the arbitrary launcher we start with.
- */
-void
-ExecJRE(char *jre, char **argv)
-{
-    char    wanted[PATH_MAX];
-    char    *execname;
-    char    *progname;
-
-    /*
-     * Resolve the real path to the directory containing the selected JRE.
-     */
-    if (realpath(jre, wanted) == NULL) {
-        fprintf(stderr, "Unable to resolve %s\n", jre);
-        exit(1);
-    }
-
-    /*
-     * Resolve the real path to the currently running launcher.
-     */
-    execname = SetExecname(argv);
-    if (execname == NULL) {
-        fprintf(stderr, "Unable to resolve current executable\n");
-        exit(1);
-    }
-
-    /*
-     * If the path to the selected JRE directory is a match to the initial
-     * portion of the path to the currently executing JRE, we have a winner!
-     * If so, just return.
-     */
-    if (strncmp(wanted, execname, strlen(wanted)) == 0)
-        return;                 /* I am the droid you were looking for */
-
-    /*
-     * If this isn't the selected version, exec the selected version.
-     */
-#ifdef JAVA_ARGS  /* javac, jar and friends. */
-    progname = "java";
-#else             /* java, oldjava, javaw and friends */
-#ifdef PROGNAME
-    progname = PROGNAME;
-#else
-    progname = *argv;
-    if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) {
-        progname = s + 1;
-    }
-#endif /* PROGNAME */
-#endif /* JAVA_ARGS */
-
-    /*
-     * This should never happen (because of the selection code in SelectJRE),
-     * but check for "impossibly" long path names just because buffer overruns
-     * can be so deadly.
-     */
-    if (strlen(wanted) + strlen(progname) + 6 > PATH_MAX) {
-        fprintf(stderr, "Path length exceeds maximum length (PATH_MAX)\n");
-        exit(1);
-    }
-
-    /*
-     * Construct the path and exec it.
-     */
-    (void)strcat(strcat(wanted, "/bin/"), progname);
-    argv[0] = progname;
-    if (_launcher_debug) {
-        int i;
-        printf("execv(\"%s\"", wanted);
-        for (i = 0; argv[i] != NULL; i++)
-            printf(", \"%s\"", argv[i]);
-        printf(")\n");
-    }
-    execv(wanted, argv);
-    fprintf(stderr, "Exec of %s failed\n", wanted);
-    exit(1);
-}
-
-#endif /* ifndef GAMMA */
-
-/*
- * "Borrowed" from Solaris 10 where the unsetenv() function is being added
- * to libc thanks to SUSv3 (Standard Unix Specification, version 3). As
- * such, in the fullness of time this will appear in libc on all relevant
- * Solaris/Linux platforms and maybe even the Windows platform.  At that
- * time, this stub can be removed.
- *
- * This implementation removes the environment locking for multithreaded
- * applications.  (We don't have access to these mutexes within libc and
- * the launcher isn't multithreaded.)  Note that what remains is platform
- * independent, because it only relies on attributes that a POSIX environment
- * defines.
- *
- * Returns 0 on success, -1 on failure.
- *
- * Also removed was the setting of errno.  The only value of errno set
- * was EINVAL ("Invalid Argument").
- */
-
-/*
- * s1(environ) is name=value
- * s2(name) is name(not the form of name=value).
- * if names match, return value of 1, else return 0
- */
-static int
-match_noeq(const char *s1, const char *s2)
-{
-        while (*s1 == *s2++) {
-                if (*s1++ == '=')
-                        return (1);
-        }
-        if (*s1 == '=' && s2[-1] == '\0')
-                return (1);
-        return (0);
-}
-
-/*
- * added for SUSv3 standard
- *
- * Delete entry from environ.
- * Do not free() memory!  Other threads may be using it.
- * Keep it around forever.
- */
-static int
-borrowed_unsetenv(const char *name)
-{
-        long    idx;            /* index into environ */
-
-        if (name == NULL || *name == '\0' ||
-            strchr(name, '=') != NULL) {
-                return (-1);
-        }
-
-        for (idx = 0; environ[idx] != NULL; idx++) {
-                if (match_noeq(environ[idx], name))
-                        break;
-        }
-        if (environ[idx] == NULL) {
-                /* name not found but still a success */
-                return (0);
-        }
-        /* squeeze up one entry */
-        do {
-                environ[idx] = environ[idx+1];
-        } while (environ[++idx] != NULL);
-
-        return (0);
-}
-/* --- End of "borrowed" code --- */
-
-/*
- * Wrapper for unsetenv() function.
- */
-int
-UnsetEnv(char *name)
-{
-    return(borrowed_unsetenv(name));
-}
-/*
- * The implementation for finding classes from the bootstrap
- * class loader, refer to java.h
- */
-static FindClassFromBootLoader_t *findBootClass = NULL;
-
-jclass
-FindBootStrapClass(JNIEnv *env, const char* classname)
-{
-   if (findBootClass == NULL) {
-       findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT,
-          "JVM_FindClassFromBootLoader");
-       if (findBootClass == NULL) {
-           fprintf(stderr, "Error: could load method JVM_FindClassFromBootLoader");
-           return NULL;
-       }
-   }
-   return findBootClass(env, classname, JNI_FALSE);
-}
-
--- a/hotspot/src/os/linux/launcher/java_md.h	Thu Dec 02 20:01:47 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK,
- * search "GAMMA" for gamma specific changes.
- */
-
-#ifndef JAVA_MD_H
-#define JAVA_MD_H
-
-#include <limits.h>
-#include <unistd.h>
-#include <sys/param.h>
-#ifndef GAMMA
-#include "manifest_info.h"
-#endif
-
-#define PATH_SEPARATOR          ':'
-#define FILESEP                 "/"
-#define FILE_SEPARATOR          '/'
-#ifndef MAXNAMELEN
-#define MAXNAMELEN              PATH_MAX
-#endif
-
-#ifdef JAVA_ARGS
-/*
- * ApplicationHome is prepended to each of these entries; the resulting
- * strings are concatenated (separated by PATH_SEPARATOR) and used as the
- * value of -cp option to the launcher.
- */
-#ifndef APP_CLASSPATH
-#define APP_CLASSPATH        { "/lib/tools.jar", "/classes" }
-#endif
-#endif
-
-#ifdef HAVE_GETHRTIME
-/*
- * Support for doing cheap, accurate interval timing.
- */
-#include <sys/time.h>
-#define CounterGet()              (gethrtime()/1000)
-#define Counter2Micros(counts)    (counts)
-#else
-#define CounterGet()              (0)
-#define Counter2Micros(counts)    (1)
-#endif /* HAVE_GETHRTIME */
-
-/*
- * Function prototypes.
- */
-#ifndef GAMMA
-char *LocateJRE(manifest_info* info);
-void ExecJRE(char *jre, char **argv);
-#endif
-int UnsetEnv(char *name);
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/posix/launcher/java_md.c	Thu Dec 02 05:45:54 2010 -0800
@@ -0,0 +1,1878 @@
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+
+#include "java.h"
+#include <dirent.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#ifndef GAMMA
+#include "manifest_info.h"
+#include "version_comp.h"
+#endif
+
+#ifdef __linux__
+#include <pthread.h>
+#else
+#include <thread.h>
+#endif
+
+#define JVM_DLL "libjvm.so"
+#define JAVA_DLL "libjava.so"
+
+#ifndef GAMMA   /* launcher.make defines ARCH */
+/*
+ * If a processor / os combination has the ability to run binaries of
+ * two data models and cohabitation of jre/jdk bits with both data
+ * models is supported, then DUAL_MODE is defined.  When DUAL_MODE is
+ * defined, the architecture names for the narrow and wide version of
+ * the architecture are defined in LIBARCH64NAME and LIBARCH32NAME.  Currently
+ * only Solaris on sparc/sparcv9 and i586/amd64 is DUAL_MODE; linux
+ * i586/amd64 could be defined as DUAL_MODE but that is not the
+ * current policy.
+ */
+
+#ifndef LIBARCHNAME
+#  error "The macro LIBARCHNAME was not defined on the compile line"
+#endif
+
+#ifdef __sun
+#  define DUAL_MODE
+#  ifndef LIBARCH32NAME
+#    error "The macro LIBARCH32NAME was not defined on the compile line"
+#  endif
+#  ifndef LIBARCH64NAME
+#    error "The macro LIBARCH64NAME was not defined on the compile line"
+#  endif
+#  include <sys/systeminfo.h>
+#  include <sys/elf.h>
+#  include <stdio.h>
+#endif
+
+#endif /* ifndef GAMMA */
+
+/* pointer to environment */
+extern char **environ;
+
+#ifndef GAMMA
+/*
+ *      A collection of useful strings. One should think of these as #define
+ *      entries, but actual strings can be more efficient (with many compilers).
+ */
+#ifdef __linux__
+static const char *system_dir   = "/usr/java";
+static const char *user_dir     = "/java";
+#else /* Solaris */
+static const char *system_dir   = "/usr/jdk";
+static const char *user_dir     = "/jdk";
+#endif
+
+#endif /* ifndef GAMMA */
+
+/*
+ * Flowchart of launcher execs and options processing on unix
+ *
+ * The selection of the proper vm shared library to open depends on
+ * several classes of command line options, including vm "flavor"
+ * options (-client, -server) and the data model options, -d32  and
+ * -d64, as well as a version specification which may have come from
+ * the command line or from the manifest of an executable jar file.
+ * The vm selection options are not passed to the running
+ * virtual machine; they must be screened out by the launcher.
+ *
+ * The version specification (if any) is processed first by the
+ * platform independent routine SelectVersion.  This may result in
+ * the exec of the specified launcher version.
+ *
+ * Typically, the launcher execs at least once to ensure a suitable
+ * LD_LIBRARY_PATH is in effect for the process.  The first exec
+ * screens out all the data model options; leaving the choice of data
+ * model implicit in the binary selected to run.  However, in case no
+ * exec is done, the data model options are screened out before the vm
+ * is invoked.
+ *
+ *  incoming argv ------------------------------
+ *  |                                          |
+ * \|/                                         |
+ * CheckJVMType                                |
+ * (removes -client, -server, etc.)            |
+ *                                            \|/
+ *                                            CreateExecutionEnvironment
+ *                                            (removes -d32 and -d64,
+ *                                             determines desired data model,
+ *                                             sets up LD_LIBRARY_PATH,
+ *                                             and exec's)
+ *                                             |
+ *  --------------------------------------------
+ *  |
+ * \|/
+ * exec child 1 incoming argv -----------------
+ *  |                                          |
+ * \|/                                         |
+ * CheckJVMType                                |
+ * (removes -client, -server, etc.)            |
+ *  |                                         \|/
+ *  |                                          CreateExecutionEnvironment
+ *  |                                          (verifies desired data model
+ *  |                                           is running and acceptable
+ *  |                                           LD_LIBRARY_PATH;
+ *  |                                           no-op in child)
+ *  |
+ * \|/
+ * TranslateDashJArgs...
+ * (Prepare to pass args to vm)
+ *  |
+ *  |
+ *  |
+ * \|/
+ * ParseArguments
+ * (ignores -d32 and -d64,
+ *  processes version options,
+ *  creates argument list for vm,
+ *  etc.)
+ *
+ */
+
+static char *SetExecname(char **argv);
+static char * GetExecname();
+static jboolean GetJVMPath(const char *jrepath, const char *jvmtype,
+                           char *jvmpath, jint jvmpathsize, char * arch);
+static jboolean GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative);
+
+#ifndef GAMMA
+const char *
+GetArch()
+{
+    return LIBARCHNAME;
+}
+#endif /* ifndef GAMMA */
+
+void
+CreateExecutionEnvironment(int *_argcp,
+                           char ***_argvp,
+                           char jrepath[],
+                           jint so_jrepath,
+                           char jvmpath[],
+                           jint so_jvmpath,
+                           char **original_argv) {
+  /*
+   * First, determine if we are running the desired data model.  If we
+   * are running the desired data model, all the error messages
+   * associated with calling GetJREPath, ReadKnownVMs, etc. should be
+   * output.  However, if we are not running the desired data model,
+   * some of the errors should be suppressed since it is more
+   * informative to issue an error message based on whether or not the
+   * os/processor combination has dual mode capabilities.
+   */
+
+    char *execname = NULL;
+    int original_argc = *_argcp;
+    jboolean jvmpathExists;
+
+    /* Compute the name of the executable */
+    execname = SetExecname(*_argvp);
+
+#ifndef GAMMA
+    /* Set the LD_LIBRARY_PATH environment variable, check data model
+       flags, and exec process, if needed */
+    {
+      char *arch        = (char *)GetArch(); /* like sparc or sparcv9 */
+      char * jvmtype    = NULL;
+      int argc          = *_argcp;
+      char **argv       = original_argv;
+
+      char *runpath     = NULL; /* existing effective LD_LIBRARY_PATH
+                                   setting */
+
+      int running       =       /* What data model is being ILP32 =>
+                                   32 bit vm; LP64 => 64 bit vm */
+#ifdef _LP64
+        64;
+#else
+      32;
+#endif
+
+      int wanted        = running;      /* What data mode is being
+                                           asked for? Current model is
+                                           fine unless another model
+                                           is asked for */
+
+      char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */
+      char* newpath     = NULL; /* path on new LD_LIBRARY_PATH */
+      char* lastslash   = NULL;
+
+      char** newenvp    = NULL; /* current environment */
+
+      char** newargv    = NULL;
+      int    newargc    = 0;
+#ifdef __sun
+      char*  dmpath     = NULL;  /* data model specific LD_LIBRARY_PATH,
+                                    Solaris only */
+#endif
+
+      /*
+       * Starting in 1.5, all unix platforms accept the -d32 and -d64
+       * options.  On platforms where only one data-model is supported
+       * (e.g. ia-64 Linux), using the flag for the other data model is
+       * an error and will terminate the program.
+       */
+
+      { /* open new scope to declare local variables */
+        int i;
+
+        newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(*newargv));
+        newargv[newargc++] = argv[0];
+
+        /* scan for data model arguments and remove from argument list;
+           last occurrence determines desired data model */
+        for (i=1; i < argc; i++) {
+
+          if (strcmp(argv[i], "-J-d64") == 0 || strcmp(argv[i], "-d64") == 0) {
+            wanted = 64;
+            continue;
+          }
+          if (strcmp(argv[i], "-J-d32") == 0 || strcmp(argv[i], "-d32") == 0) {
+            wanted = 32;
+            continue;
+          }
+          newargv[newargc++] = argv[i];
+
+#ifdef JAVA_ARGS
+          if (argv[i][0] != '-')
+            continue;
+#else
+          if (strcmp(argv[i], "-classpath") == 0 || strcmp(argv[i], "-cp") == 0) {
+            i++;
+            if (i >= argc) break;
+            newargv[newargc++] = argv[i];
+            continue;
+          }
+          if (argv[i][0] != '-') { i++; break; }
+#endif
+        }
+
+        /* copy rest of args [i .. argc) */
+        while (i < argc) {
+          newargv[newargc++] = argv[i++];
+        }
+        newargv[newargc] = NULL;
+
+        /*
+         * newargv has all proper arguments here
+         */
+
+        argc = newargc;
+        argv = newargv;
+      }
+
+      /* If the data model is not changing, it is an error if the
+         jvmpath does not exist */
+      if (wanted == running) {
+        /* Find out where the JRE is that we will be using. */
+        if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) {
+          fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n");
+          exit(2);
+        }
+
+        /* Find the specified JVM type */
+        if (ReadKnownVMs(jrepath, arch, JNI_FALSE) < 1) {
+          fprintf(stderr, "Error: no known VMs. (check for corrupt jvm.cfg file)\n");
+          exit(1);
+        }
+
+        jvmpath[0] = '\0';
+        jvmtype = CheckJvmType(_argcp, _argvp, JNI_FALSE);
+
+        if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch )) {
+          fprintf(stderr, "Error: no `%s' JVM at `%s'.\n", jvmtype, jvmpath);
+          exit(4);
+        }
+      } else {  /* do the same speculatively or exit */
+#ifdef DUAL_MODE
+        if (running != wanted) {
+          /* Find out where the JRE is that we will be using. */
+          if (!GetJREPath(jrepath, so_jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE)) {
+            goto EndDataModelSpeculate;
+          }
+
+          /*
+           * Read in jvm.cfg for target data model and process vm
+           * selection options.
+           */
+          if (ReadKnownVMs(jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE) < 1) {
+            goto EndDataModelSpeculate;
+          }
+          jvmpath[0] = '\0';
+          jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE);
+          /* exec child can do error checking on the existence of the path */
+          jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath,
+                                     ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME));
+
+        }
+      EndDataModelSpeculate: /* give up and let other code report error message */
+        ;
+#else
+        fprintf(stderr, "Running a %d-bit JVM is not supported on this platform.\n", wanted);
+        exit(1);
+#endif
+      }
+
+      /*
+       * We will set the LD_LIBRARY_PATH as follows:
+       *
+       *     o          $JVMPATH (directory portion only)
+       *     o          $JRE/lib/$LIBARCHNAME
+       *     o          $JRE/../lib/$LIBARCHNAME
+       *
+       * followed by the user's previous effective LD_LIBRARY_PATH, if
+       * any.
+       */
+
+#ifdef __sun
+      /*
+       * Starting in Solaris 7, ld.so.1 supports three LD_LIBRARY_PATH
+       * variables:
+       *
+       * 1. LD_LIBRARY_PATH -- used for 32 and 64 bit searches if
+       * data-model specific variables are not set.
+       *
+       * 2. LD_LIBRARY_PATH_64 -- overrides and replaces LD_LIBRARY_PATH
+       * for 64-bit binaries.
+       *
+       * 3. LD_LIBRARY_PATH_32 -- overrides and replaces LD_LIBRARY_PATH
+       * for 32-bit binaries.
+       *
+       * The vm uses LD_LIBRARY_PATH to set the java.library.path system
+       * property.  To shield the vm from the complication of multiple
+       * LD_LIBRARY_PATH variables, if the appropriate data model
+       * specific variable is set, we will act as if LD_LIBRARY_PATH had
+       * the value of the data model specific variant and the data model
+       * specific variant will be unset.  Note that the variable for the
+       * *wanted* data model must be used (if it is set), not simply the
+       * current running data model.
+       */
+
+      switch(wanted) {
+      case 0:
+        if(running == 32) {
+          dmpath = getenv("LD_LIBRARY_PATH_32");
+          wanted = 32;
+        }
+        else {
+          dmpath = getenv("LD_LIBRARY_PATH_64");
+          wanted = 64;
+        }
+        break;
+
+      case 32:
+        dmpath = getenv("LD_LIBRARY_PATH_32");
+        break;
+
+      case 64:
+        dmpath = getenv("LD_LIBRARY_PATH_64");
+        break;
+
+      default:
+        fprintf(stderr, "Improper value at line %d.", __LINE__);
+        exit(1); /* unknown value in wanted */
+        break;
+      }
+
+      /*
+       * If dmpath is NULL, the relevant data model specific variable is
+       * not set and normal LD_LIBRARY_PATH should be used.
+       */
+      if( dmpath == NULL) {
+        runpath = getenv("LD_LIBRARY_PATH");
+      }
+      else {
+        runpath = dmpath;
+      }
+#else
+      /*
+       * If not on Solaris, assume only a single LD_LIBRARY_PATH
+       * variable.
+       */
+      runpath = getenv("LD_LIBRARY_PATH");
+#endif /* __sun */
+
+#ifdef __linux
+      /*
+       * On linux, if a binary is running as sgid or suid, glibc sets
+       * LD_LIBRARY_PATH to the empty string for security purposes.  (In
+       * contrast, on Solaris the LD_LIBRARY_PATH variable for a
+       * privileged binary does not lose its settings; but the dynamic
+       * linker does apply more scrutiny to the path.) The launcher uses
+       * the value of LD_LIBRARY_PATH to prevent an exec loop.
+       * Therefore, if we are running sgid or suid, this function's
+       * setting of LD_LIBRARY_PATH will be ineffective and we should
+       * return from the function now.  Getting the right libraries to
+       * be found must be handled through other mechanisms.
+       */
+      if((getgid() != getegid()) || (getuid() != geteuid()) ) {
+        return;
+      }
+#endif
+
+      /* runpath contains current effective LD_LIBRARY_PATH setting */
+
+      jvmpath = JLI_StringDup(jvmpath);
+      new_runpath = JLI_MemAlloc( ((runpath!=NULL)?strlen(runpath):0) +
+                              2*strlen(jrepath) + 2*strlen(arch) +
+                              strlen(jvmpath) + 52);
+      newpath = new_runpath + strlen("LD_LIBRARY_PATH=");
+
+
+      /*
+       * Create desired LD_LIBRARY_PATH value for target data model.
+       */
+      {
+        /* remove the name of the .so from the JVM path */
+        lastslash = strrchr(jvmpath, '/');
+        if (lastslash)
+          *lastslash = '\0';
+
+
+        /* jvmpath, ((running != wanted)?((wanted==64)?"/"LIBARCH64NAME:"/.."):""), */
+
+        sprintf(new_runpath, "LD_LIBRARY_PATH="
+                "%s:"
+                "%s/lib/%s:"
+                "%s/../lib/%s",
+                jvmpath,
+#ifdef DUAL_MODE
+                jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME),
+                jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME)
+#else
+                jrepath, arch,
+                jrepath, arch
+#endif
+                );
+
+
+        /*
+         * Check to make sure that the prefix of the current path is the
+         * desired environment variable setting.
+         */
+        if (runpath != NULL &&
+            strncmp(newpath, runpath, strlen(newpath))==0 &&
+            (runpath[strlen(newpath)] == 0 || runpath[strlen(newpath)] == ':') &&
+            (running == wanted) /* data model does not have to be changed */
+#ifdef __sun
+            && (dmpath == NULL)    /* data model specific variables not set  */
+#endif
+            ) {
+
+          return;
+
+        }
+      }
+
+      /*
+       * Place the desired environment setting onto the prefix of
+       * LD_LIBRARY_PATH.  Note that this prevents any possible infinite
+       * loop of execv() because we test for the prefix, above.
+       */
+      if (runpath != 0) {
+        strcat(new_runpath, ":");
+        strcat(new_runpath, runpath);
+      }
+
+      if( putenv(new_runpath) != 0) {
+        exit(1); /* problem allocating memory; LD_LIBRARY_PATH not set
+                    properly */
+      }
+
+      /*
+       * Unix systems document that they look at LD_LIBRARY_PATH only
+       * once at startup, so we have to re-exec the current executable
+       * to get the changed environment variable to have an effect.
+       */
+
+#ifdef __sun
+      /*
+       * If dmpath is not NULL, remove the data model specific string
+       * in the environment for the exec'ed child.
+       */
+
+      if( dmpath != NULL)
+        (void)UnsetEnv((wanted==32)?"LD_LIBRARY_PATH_32":"LD_LIBRARY_PATH_64");
+#endif
+
+      newenvp = environ;
+
+      {
+        char *newexec = execname;
+#ifdef DUAL_MODE
+        /*
+         * If the data model is being changed, the path to the
+         * executable must be updated accordingly; the executable name
+         * and directory the executable resides in are separate.  In the
+         * case of 32 => 64, the new bits are assumed to reside in, e.g.
+         * "olddir/LIBARCH64NAME/execname"; in the case of 64 => 32,
+         * the bits are assumed to be in "olddir/../execname".  For example,
+         *
+         * olddir/sparcv9/execname
+         * olddir/amd64/execname
+         *
+         * for Solaris SPARC and Linux amd64, respectively.
+         */
+
+        if (running != wanted) {
+          char *oldexec = strcpy(JLI_MemAlloc(strlen(execname) + 1), execname);
+          char *olddir = oldexec;
+          char *oldbase = strrchr(oldexec, '/');
+
+
+          newexec = JLI_MemAlloc(strlen(execname) + 20);
+          *oldbase++ = 0;
+          sprintf(newexec, "%s/%s/%s", olddir,
+                  ((wanted==64) ? LIBARCH64NAME : ".."), oldbase);
+          argv[0] = newexec;
+        }
+#endif
+
+        (void)fflush(stdout);
+        (void)fflush(stderr);
+        execve(newexec, argv, newenvp);
+        perror("execve()");
+
+        fprintf(stderr, "Error trying to exec %s.\n", newexec);
+        fprintf(stderr, "Check if file exists and permissions are set correctly.\n");
+
+#ifdef DUAL_MODE
+        if (running != wanted) {
+          fprintf(stderr, "Failed to start a %d-bit JVM process from a %d-bit JVM.\n",
+                  wanted, running);
+#  ifdef __sun
+
+#    ifdef __sparc
+          fprintf(stderr, "Verify all necessary J2SE components have been installed.\n" );
+          fprintf(stderr,
+                  "(Solaris SPARC 64-bit components must be installed after 32-bit components.)\n" );
+#    else
+          fprintf(stderr, "Either 64-bit processes are not supported by this platform\n");
+          fprintf(stderr, "or the 64-bit components have not been installed.\n");
+#    endif
+        }
+#  endif
+#endif
+
+      }
+
+      exit(1);
+    }
+
+#else  /* ifndef GAMMA */
+
+  /*
+   * gamma launcher is simpler in that it doesn't handle VM flavors, data
+   * model, LD_LIBRARY_PATH, etc. Assuming everything is set-up correctly
+   * all we need to do here is to return correct path names. See also
+   * GetJVMPath() and GetApplicationHome().
+   */
+
+  { char *arch = (char *) ARCH; /* like sparc or sparcv9 */
+    char *p;
+
+    if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) {
+      fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n");
+      exit(2);
+    }
+
+    if (!GetJVMPath(jrepath, NULL, jvmpath, so_jvmpath, arch )) {
+      fprintf(stderr, "Error: no JVM at `%s'.\n", jvmpath);
+      exit(4);
+    }
+  }
+
+#endif  /* ifndef GAMMA */
+}
+
+
+/*
+ * On Solaris VM choosing is done by the launcher (java.c).
+ */
+static jboolean
+GetJVMPath(const char *jrepath, const char *jvmtype,
+           char *jvmpath, jint jvmpathsize, char * arch)
+{
+    struct stat s;
+
+#ifndef GAMMA
+    if (strchr(jvmtype, '/')) {
+        sprintf(jvmpath, "%s/" JVM_DLL, jvmtype);
+    } else {
+        sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
+    }
+#else
+    /*
+     * For gamma launcher, JVM is either built-in or in the same directory.
+     * Either way we return "<exe_path>/libjvm.so" where <exe_path> is the
+     * directory where gamma launcher is located.
+     */
+
+    char *p;
+
+    snprintf(jvmpath, jvmpathsize, "%s", GetExecname());
+    p = strrchr(jvmpath, '/');
+    if (p) {
+       /* replace executable name with libjvm.so */
+       snprintf(p + 1, jvmpathsize - (p + 1 - jvmpath), "%s", JVM_DLL);
+    } else {
+       /* this case shouldn't happen */
+       snprintf(jvmpath, jvmpathsize, "%s", JVM_DLL);
+    }
+#endif /* ifndef GAMMA */
+
+    if (_launcher_debug)
+      printf("Does `%s' exist ... ", jvmpath);
+
+    if (stat(jvmpath, &s) == 0) {
+        if (_launcher_debug)
+          printf("yes.\n");
+        return JNI_TRUE;
+    } else {
+        if (_launcher_debug)
+          printf("no.\n");
+        return JNI_FALSE;
+    }
+}
+
+/*
+ * Find path to JRE based on .exe's location or registry settings.
+ */
+static jboolean
+GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative)
+{
+    char libjava[MAXPATHLEN];
+
+    if (GetApplicationHome(path, pathsize)) {
+        /* Is JRE co-located with the application? */
+        sprintf(libjava, "%s/lib/%s/" JAVA_DLL, path, arch);
+        if (access(libjava, F_OK) == 0) {
+            goto found;
+        }
+
+        /* Does the app ship a private JRE in <apphome>/jre directory? */
+        sprintf(libjava, "%s/jre/lib/%s/" JAVA_DLL, path, arch);
+        if (access(libjava, F_OK) == 0) {
+            strcat(path, "/jre");
+            goto found;
+        }
+    }
+
+    if (!speculative)
+      fprintf(stderr, "Error: could not find " JAVA_DLL "\n");
+    return JNI_FALSE;
+
+ found:
+    if (_launcher_debug)
+      printf("JRE path is %s\n", path);
+    return JNI_TRUE;
+}
+
+jboolean
+LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
+{
+#ifdef GAMMA
+    /* JVM is directly linked with gamma launcher; no dlopen() */
+    ifn->CreateJavaVM = JNI_CreateJavaVM;
+    ifn->GetDefaultJavaVMInitArgs = JNI_GetDefaultJavaVMInitArgs;
+    return JNI_TRUE;
+#else
+   Dl_info dlinfo;
+    void *libjvm;
+
+    if (_launcher_debug) {
+        printf("JVM path is %s\n", jvmpath);
+    }
+
+    libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
+    if (libjvm == NULL) {
+#if defined(__sparc) && !defined(_LP64) /* i.e. 32-bit sparc */
+      FILE * fp;
+      Elf32_Ehdr elf_head;
+      int count;
+      int location;
+
+      fp = fopen(jvmpath, "r");
+      if(fp == NULL)
+        goto error;
+
+      /* read in elf header */
+      count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp);
+      fclose(fp);
+      if(count < 1)
+        goto error;
+
+      /*
+       * Check for running a server vm (compiled with -xarch=v8plus)
+       * on a stock v8 processor.  In this case, the machine type in
+       * the elf header would not be included the architecture list
+       * provided by the isalist command, which is turn is gotten from
+       * sysinfo.  This case cannot occur on 64-bit hardware and thus
+       * does not have to be checked for in binaries with an LP64 data
+       * model.
+       */
+      if(elf_head.e_machine == EM_SPARC32PLUS) {
+        char buf[257];  /* recommended buffer size from sysinfo man
+                           page */
+        long length;
+        char* location;
+
+        length = sysinfo(SI_ISALIST, buf, 257);
+        if(length > 0) {
+          location = strstr(buf, "sparcv8plus ");
+          if(location == NULL) {
+            fprintf(stderr, "SPARC V8 processor detected; Server compiler requires V9 or better.\n");
+            fprintf(stderr, "Use Client compiler on V8 processors.\n");
+            fprintf(stderr, "Could not create the Java virtual machine.\n");
+            return JNI_FALSE;
+          }
+        }
+      }
+#endif
+      fprintf(stderr, "dl failure on line %d", __LINE__);
+      goto error;
+    }
+
+    ifn->CreateJavaVM = (CreateJavaVM_t)
+      dlsym(libjvm, "JNI_CreateJavaVM");
+    if (ifn->CreateJavaVM == NULL)
+        goto error;
+
+    ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
+        dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");
+    if (ifn->GetDefaultJavaVMInitArgs == NULL)
+      goto error;
+
+    return JNI_TRUE;
+
+error:
+    fprintf(stderr, "Error: failed %s, because %s\n", jvmpath, dlerror());
+    return JNI_FALSE;
+#endif /* ifndef GAMMA */
+}
+
+/*
+ * If app is "/foo/bin/javac", or "/foo/bin/sparcv9/javac" then put
+ * "/foo" into buf.
+ */
+jboolean
+GetApplicationHome(char *buf, jint bufsize)
+{
+#ifdef __linux__
+    char *execname = GetExecname();
+    if (execname) {
+        strncpy(buf, execname, bufsize-1);
+        buf[bufsize-1] = '\0';
+    } else {
+        return JNI_FALSE;
+    }
+#else
+    Dl_info dlinfo;
+
+    dladdr((void *)GetApplicationHome, &dlinfo);
+    if (realpath(dlinfo.dli_fname, buf) == NULL) {
+        fprintf(stderr, "Error: realpath(`%s') failed.\n", dlinfo.dli_fname);
+        return JNI_FALSE;
+    }
+#endif
+
+#ifdef GAMMA
+    {
+       /* gamma launcher uses JAVA_HOME or ALT_JAVA_HOME environment variable to find JDK/JRE */
+       char* java_home_var = getenv("ALT_JAVA_HOME");
+       if (java_home_var == NULL) {
+          java_home_var = getenv("JAVA_HOME");
+       }
+       if (java_home_var == NULL) {
+          printf("JAVA_HOME or ALT_JAVA_HOME must point to a valid JDK/JRE to run gamma\n");
+          return JNI_FALSE;
+       }
+       snprintf(buf, bufsize, "%s", java_home_var);
+    }
+#else
+    if (strrchr(buf, '/') == 0) {
+        buf[0] = '\0';
+        return JNI_FALSE;
+    }
+    *(strrchr(buf, '/')) = '\0';        /* executable file      */
+    if (strlen(buf) < 4 || strrchr(buf, '/') == 0) {
+        buf[0] = '\0';
+        return JNI_FALSE;
+    }
+    if (strcmp("/bin", buf + strlen(buf) - 4) != 0)
+        *(strrchr(buf, '/')) = '\0';    /* sparcv9 or amd64     */
+    if (strlen(buf) < 4 || strcmp("/bin", buf + strlen(buf) - 4) != 0) {
+        buf[0] = '\0';
+        return JNI_FALSE;
+    }
+    *(strrchr(buf, '/')) = '\0';        /* bin                  */
+#endif /* ifndef GAMMA */
+
+    return JNI_TRUE;
+}
+
+
+/*
+ * Return true if the named program exists
+ */
+static int
+ProgramExists(char *name)
+{
+    struct stat sb;
+    if (stat(name, &sb) != 0) return 0;
+    if (S_ISDIR(sb.st_mode)) return 0;
+    return (sb.st_mode & S_IEXEC) != 0;
+}
+
+
+/*
+ * Find a command in a directory, returning the path.
+ */
+static char *
+Resolve(char *indir, char *cmd)
+{
+    char name[PATH_MAX + 2], *real;
+
+    if ((strlen(indir) + strlen(cmd) + 1)  > PATH_MAX) return 0;
+    sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd);
+    if (!ProgramExists(name)) return 0;
+    real = JLI_MemAlloc(PATH_MAX + 2);
+    if (!realpath(name, real))
+        strcpy(real, name);
+    return real;
+}
+
+
+/*
+ * Find a path for the executable
+ */
+static char *
+FindExecName(char *program)
+{
+    char cwdbuf[PATH_MAX+2];
+    char *path;
+    char *tmp_path;
+    char *f;
+    char *result = NULL;
+
+    /* absolute path? */
+    if (*program == FILE_SEPARATOR ||
+        (FILE_SEPARATOR=='\\' && strrchr(program, ':')))
+        return Resolve("", program+1);
+
+    /* relative path? */
+    if (strrchr(program, FILE_SEPARATOR) != 0) {
+        char buf[PATH_MAX+2];
+        return Resolve(getcwd(cwdbuf, sizeof(cwdbuf)), program);
+    }
+
+    /* from search path? */
+    path = getenv("PATH");
+    if (!path || !*path) path = ".";
+    tmp_path = JLI_MemAlloc(strlen(path) + 2);
+    strcpy(tmp_path, path);
+
+    for (f=tmp_path; *f && result==0; ) {
+        char *s = f;
+        while (*f && (*f != PATH_SEPARATOR)) ++f;
+        if (*f) *f++ = 0;
+        if (*s == FILE_SEPARATOR)
+            result = Resolve(s, program);
+        else {
+            /* relative path element */
+            char dir[2*PATH_MAX];
+            sprintf(dir, "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)),
+                    FILE_SEPARATOR, s);
+            result = Resolve(dir, program);
+        }
+        if (result != 0) break;
+    }
+
+    JLI_MemFree(tmp_path);
+    return result;
+}
+
+
+/* Store the name of the executable once computed */
+static char *execname = NULL;
+
+/*
+ * Compute the name of the executable
+ *
+ * In order to re-exec securely we need the absolute path of the
+ * executable. On Solaris getexecname(3c) may not return an absolute
+ * path so we use dladdr to get the filename of the executable and
+ * then use realpath to derive an absolute path. From Solaris 9
+ * onwards the filename returned in DL_info structure from dladdr is
+ * an absolute pathname so technically realpath isn't required.
+ * On Linux we read the executable name from /proc/self/exe.
+ * As a fallback, and for platforms other than Solaris and Linux,
+ * we use FindExecName to compute the executable name.
+ */
+static char *
+SetExecname(char **argv)
+{
+    char* exec_path = NULL;
+
+    if (execname != NULL)       /* Already determined */
+        return (execname);
+
+#if defined(__sun)
+    {
+        Dl_info dlinfo;
+        if (dladdr((void*)&SetExecname, &dlinfo)) {
+            char *resolved = (char*)JLI_MemAlloc(PATH_MAX+1);
+            if (resolved != NULL) {
+                exec_path = realpath(dlinfo.dli_fname, resolved);
+                if (exec_path == NULL) {
+                    JLI_MemFree(resolved);
+                }
+            }
+        }
+    }
+#elif defined(__linux__)
+    {
+        const char* self = "/proc/self/exe";
+        char buf[PATH_MAX+1];
+        int len = readlink(self, buf, PATH_MAX);
+        if (len >= 0) {
+            buf[len] = '\0';            /* readlink doesn't nul terminate */
+            exec_path = JLI_StringDup(buf);
+        }
+    }
+#else /* !__sun && !__linux */
+    {
+        /* Not implemented */
+    }
+#endif
+
+    if (exec_path == NULL) {
+        exec_path = FindExecName(argv[0]);
+    }
+    execname = exec_path;
+    return exec_path;
+}
+
+/*
+ * Return the name of the executable.  Used in java_md.c to find the JRE area.
+ */
+static char *
+GetExecname() {
+  return execname;
+}
+
+void ReportErrorMessage(char * message, jboolean always) {
+  if (always) {
+    fprintf(stderr, "%s\n", message);
+  }
+}
+
+void ReportErrorMessage2(char * format, char * string, jboolean always) {
+  if (always) {
+    fprintf(stderr, format, string);
+    fprintf(stderr, "\n");
+  }
+}
+
+void  ReportExceptionDescription(JNIEnv * env) {
+  (*env)->ExceptionDescribe(env);
+}
+
+/*
+ * Return JNI_TRUE for an option string that has no effect but should
+ * _not_ be passed on to the vm; return JNI_FALSE otherwise.  On
+ * Solaris SPARC, this screening needs to be done if:
+ * 1) LD_LIBRARY_PATH does _not_ need to be reset and
+ * 2) -d32 or -d64 is passed to a binary with a matching data model
+ *    (the exec in SetLibraryPath removes -d<n> options and points the
+ *    exec to the proper binary).  When this exec is not done, these options
+ *    would end up getting passed onto the vm.
+ */
+jboolean RemovableMachineDependentOption(char * option) {
+  /*
+   * Unconditionally remove both -d32 and -d64 options since only
+   * the last such options has an effect; e.g.
+   * java -d32 -d64 -d32 -version
+   * is equivalent to
+   * java -d32 -version
+   */
+
+  if( (strcmp(option, "-d32")  == 0 ) ||
+      (strcmp(option, "-d64")  == 0 ))
+    return JNI_TRUE;
+  else
+    return JNI_FALSE;
+}
+
+void PrintMachineDependentOptions() {
+      fprintf(stdout,
+        "    -d32          use a 32-bit data model if available\n"
+        "\n"
+        "    -d64          use a 64-bit data model if available\n");
+      return;
+}
+
+#ifndef GAMMA
+/*
+ * The following methods (down to ServerClassMachine()) answer
+ * the question about whether a machine is a "server-class"
+ * machine.  A server-class machine is loosely defined as one
+ * with 2 or more processors and 2 gigabytes or more physical
+ * memory.  The definition of a processor is a physical package,
+ * not a hyperthreaded chip masquerading as a multi-processor.
+ * The definition of memory is also somewhat fuzzy, since x86
+ * machines seem not to report all the memory in their DIMMs, we
+ * think because of memory mapping of graphics cards, etc.
+ *
+ * This code is somewhat more confused with #ifdef's than we'd
+ * like because this file is used by both Solaris and Linux
+ * platforms, and so needs to be parameterized for SPARC and
+ * i586 hardware.  The other Linux platforms (amd64 and ia64)
+ * don't even ask this question, because they only come with
+ * server JVMs.  */
+
+# define KB (1024UL)
+# define MB (1024UL * KB)
+# define GB (1024UL * MB)
+
+/* Compute physical memory by asking the OS */
+uint64_t
+physical_memory(void) {
+  const uint64_t pages     = (uint64_t) sysconf(_SC_PHYS_PAGES);
+  const uint64_t page_size = (uint64_t) sysconf(_SC_PAGESIZE);
+  const uint64_t result    = pages * page_size;
+# define UINT64_FORMAT "%" PRIu64
+
+  if (_launcher_debug) {
+    printf("pages: " UINT64_FORMAT
+           "  page_size: " UINT64_FORMAT
+           "  physical memory: " UINT64_FORMAT " (%.3fGB)\n",
+           pages, page_size, result, result / (double) GB);
+  }
+  return result;
+}
+
+#if defined(__sun) && defined(__sparc)
+
+/* Methods for solaris-sparc: these are easy. */
+
+/* Ask the OS how many processors there are. */
+unsigned long
+physical_processors(void) {
+  const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
+
+  if (_launcher_debug) {
+    printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
+  }
+  return sys_processors;
+}
+
+/* The solaris-sparc version of the "server-class" predicate. */
+jboolean
+solaris_sparc_ServerClassMachine(void) {
+  jboolean            result            = JNI_FALSE;
+  /* How big is a server class machine? */
+  const unsigned long server_processors = 2UL;
+  const uint64_t      server_memory     = 2UL * GB;
+  const uint64_t      actual_memory     = physical_memory();
+
+  /* Is this a server class machine? */
+  if (actual_memory >= server_memory) {
+    const unsigned long actual_processors = physical_processors();
+    if (actual_processors >= server_processors) {
+      result = JNI_TRUE;
+    }
+  }
+  if (_launcher_debug) {
+    printf("solaris_" LIBARCHNAME "_ServerClassMachine: %s\n",
+           (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE"));
+  }
+  return result;
+}
+
+#endif /* __sun && __sparc */
+
+#if defined(__sun) && defined(i586)
+
+/*
+ * A utility method for asking the CPU about itself.
+ * There's a corresponding version of linux-i586
+ * because the compilers are different.
+ */
+void
+get_cpuid(uint32_t arg,
+          uint32_t* eaxp,
+          uint32_t* ebxp,
+          uint32_t* ecxp,
+          uint32_t* edxp) {
+#ifdef _LP64
+  asm(
+  /* rbx is a callee-saved register */
+      " movq    %rbx, %r11  \n"
+  /* rdx and rcx are 3rd and 4th argument registers */
+      " movq    %rdx, %r10  \n"
+      " movq    %rcx, %r9   \n"
+      " movl    %edi, %eax  \n"
+      " cpuid               \n"
+      " movl    %eax, (%rsi)\n"
+      " movl    %ebx, (%r10)\n"
+      " movl    %ecx, (%r9) \n"
+      " movl    %edx, (%r8) \n"
+  /* Restore rbx */
+      " movq    %r11, %rbx");
+#else
+  /* EBX is a callee-saved register */
+  asm(" pushl   %ebx");
+  /* Need ESI for storing through arguments */
+  asm(" pushl   %esi");
+  asm(" movl    8(%ebp), %eax   \n"
+      " cpuid                   \n"
+      " movl    12(%ebp), %esi  \n"
+      " movl    %eax, (%esi)    \n"
+      " movl    16(%ebp), %esi  \n"
+      " movl    %ebx, (%esi)    \n"
+      " movl    20(%ebp), %esi  \n"
+      " movl    %ecx, (%esi)    \n"
+      " movl    24(%ebp), %esi  \n"
+      " movl    %edx, (%esi)      ");
+  /* Restore ESI and EBX */
+  asm(" popl    %esi");
+  /* Restore EBX */
+  asm(" popl    %ebx");
+#endif
+}
+
+#endif /* __sun && i586 */
+
+#if defined(__linux__) && defined(i586)
+
+/*
+ * A utility method for asking the CPU about itself.
+ * There's a corresponding version of solaris-i586
+ * because the compilers are different.
+ */
+void
+get_cpuid(uint32_t arg,
+          uint32_t* eaxp,
+          uint32_t* ebxp,
+          uint32_t* ecxp,
+          uint32_t* edxp) {
+#ifdef _LP64
+  __asm__ volatile (/* Instructions */
+                    "   movl    %4, %%eax  \n"
+                    "   cpuid              \n"
+                    "   movl    %%eax, (%0)\n"
+                    "   movl    %%ebx, (%1)\n"
+                    "   movl    %%ecx, (%2)\n"
+                    "   movl    %%edx, (%3)\n"
+                    : /* Outputs */
+                    : /* Inputs */
+                    "r" (eaxp),
+                    "r" (ebxp),
+                    "r" (ecxp),
+                    "r" (edxp),
+                    "r" (arg)
+                    : /* Clobbers */
+                    "%rax", "%rbx", "%rcx", "%rdx", "memory"
+                    );
+#else
+  uint32_t value_of_eax = 0;
+  uint32_t value_of_ebx = 0;
+  uint32_t value_of_ecx = 0;
+  uint32_t value_of_edx = 0;
+  __asm__ volatile (/* Instructions */
+                        /* ebx is callee-save, so push it */
+                    "   pushl   %%ebx      \n"
+                    "   movl    %4, %%eax  \n"
+                    "   cpuid              \n"
+                    "   movl    %%eax, %0  \n"
+                    "   movl    %%ebx, %1  \n"
+                    "   movl    %%ecx, %2  \n"
+                    "   movl    %%edx, %3  \n"
+                        /* restore ebx */
+                    "   popl    %%ebx      \n"
+
+                    : /* Outputs */
+                    "=m" (value_of_eax),
+                    "=m" (value_of_ebx),
+                    "=m" (value_of_ecx),
+                    "=m" (value_of_edx)
+                    : /* Inputs */
+                    "m" (arg)
+                    : /* Clobbers */
+                    "%eax", "%ecx", "%edx"
+                    );
+  *eaxp = value_of_eax;
+  *ebxp = value_of_ebx;
+  *ecxp = value_of_ecx;
+  *edxp = value_of_edx;
+#endif
+}
+
+#endif /* __linux__ && i586 */
+
+#ifdef i586
+/*
+ * Routines shared by solaris-i586 and linux-i586.
+ */
+
+enum HyperThreadingSupport_enum {
+  hts_supported        =  1,
+  hts_too_soon_to_tell =  0,
+  hts_not_supported    = -1,
+  hts_not_pentium4     = -2,
+  hts_not_intel        = -3
+};
+typedef enum HyperThreadingSupport_enum HyperThreadingSupport;
+
+/* Determine if hyperthreading is supported */
+HyperThreadingSupport
+hyperthreading_support(void) {
+  HyperThreadingSupport result = hts_too_soon_to_tell;
+  /* Bits 11 through 8 is family processor id */
+# define FAMILY_ID_SHIFT 8
+# define FAMILY_ID_MASK 0xf
+  /* Bits 23 through 20 is extended family processor id */
+# define EXT_FAMILY_ID_SHIFT 20
+# define EXT_FAMILY_ID_MASK 0xf
+  /* Pentium 4 family processor id */
+# define PENTIUM4_FAMILY_ID 0xf
+  /* Bit 28 indicates Hyper-Threading Technology support */
+# define HT_BIT_SHIFT 28
+# define HT_BIT_MASK 1
+  uint32_t vendor_id[3] = { 0U, 0U, 0U };
+  uint32_t value_of_eax = 0U;
+  uint32_t value_of_edx = 0U;
+  uint32_t dummy        = 0U;
+
+  /* Yes, this is supposed to be [0], [2], [1] */
+  get_cpuid(0, &dummy, &vendor_id[0], &vendor_id[2], &vendor_id[1]);
+  if (_launcher_debug) {
+    printf("vendor: %c %c %c %c %c %c %c %c %c %c %c %c \n",
+           ((vendor_id[0] >>  0) & 0xff),
+           ((vendor_id[0] >>  8) & 0xff),
+           ((vendor_id[0] >> 16) & 0xff),
+           ((vendor_id[0] >> 24) & 0xff),
+           ((vendor_id[1] >>  0) & 0xff),
+           ((vendor_id[1] >>  8) & 0xff),
+           ((vendor_id[1] >> 16) & 0xff),
+           ((vendor_id[1] >> 24) & 0xff),
+           ((vendor_id[2] >>  0) & 0xff),
+           ((vendor_id[2] >>  8) & 0xff),
+           ((vendor_id[2] >> 16) & 0xff),
+           ((vendor_id[2] >> 24) & 0xff));
+  }
+  get_cpuid(1, &value_of_eax, &dummy, &dummy, &value_of_edx);
+  if (_launcher_debug) {
+    printf("value_of_eax: 0x%x  value_of_edx: 0x%x\n",
+           value_of_eax, value_of_edx);
+  }
+  if ((((value_of_eax >> FAMILY_ID_SHIFT) & FAMILY_ID_MASK) == PENTIUM4_FAMILY_ID) ||
+      (((value_of_eax >> EXT_FAMILY_ID_SHIFT) & EXT_FAMILY_ID_MASK) != 0)) {
+    if ((((vendor_id[0] >>  0) & 0xff) == 'G') &&
+        (((vendor_id[0] >>  8) & 0xff) == 'e') &&
+        (((vendor_id[0] >> 16) & 0xff) == 'n') &&
+        (((vendor_id[0] >> 24) & 0xff) == 'u') &&
+        (((vendor_id[1] >>  0) & 0xff) == 'i') &&
+        (((vendor_id[1] >>  8) & 0xff) == 'n') &&
+        (((vendor_id[1] >> 16) & 0xff) == 'e') &&
+        (((vendor_id[1] >> 24) & 0xff) == 'I') &&
+        (((vendor_id[2] >>  0) & 0xff) == 'n') &&
+        (((vendor_id[2] >>  8) & 0xff) == 't') &&
+        (((vendor_id[2] >> 16) & 0xff) == 'e') &&
+        (((vendor_id[2] >> 24) & 0xff) == 'l')) {
+      if (((value_of_edx >> HT_BIT_SHIFT) & HT_BIT_MASK) == HT_BIT_MASK) {
+        if (_launcher_debug) {
+          printf("Hyperthreading supported\n");
+        }
+        result = hts_supported;
+      } else {
+        if (_launcher_debug) {
+          printf("Hyperthreading not supported\n");
+        }
+        result = hts_not_supported;
+      }
+    } else {
+      if (_launcher_debug) {
+        printf("Not GenuineIntel\n");
+      }
+      result = hts_not_intel;
+    }
+  } else {
+    if (_launcher_debug) {
+      printf("not Pentium 4 or extended\n");
+    }
+    result = hts_not_pentium4;
+  }
+  return result;
+}
+
+/* Determine how many logical processors there are per CPU */
+unsigned int
+logical_processors_per_package(void) {
+  /*
+   * After CPUID with EAX==1, register EBX bits 23 through 16
+   * indicate the number of logical processors per package
+   */
+# define NUM_LOGICAL_SHIFT 16
+# define NUM_LOGICAL_MASK 0xff
+  unsigned int result                        = 1U;
+  const HyperThreadingSupport hyperthreading = hyperthreading_support();
+
+  if (hyperthreading == hts_supported) {
+    uint32_t value_of_ebx = 0U;
+    uint32_t dummy        = 0U;
+
+    get_cpuid(1, &dummy, &value_of_ebx, &dummy, &dummy);
+    result = (value_of_ebx >> NUM_LOGICAL_SHIFT) & NUM_LOGICAL_MASK;
+    if (_launcher_debug) {
+      printf("logical processors per package: %u\n", result);
+    }
+  }
+  return result;
+}
+
+/* Compute the number of physical processors, not logical processors */
+unsigned long
+physical_processors(void) {
+  const long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
+  unsigned long result      = sys_processors;
+
+  if (_launcher_debug) {
+    printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
+  }
+  if (sys_processors > 1) {
+    unsigned int logical_processors = logical_processors_per_package();
+    if (logical_processors > 1) {
+      result = (unsigned long) sys_processors / logical_processors;
+    }
+  }
+  if (_launcher_debug) {
+    printf("physical processors: %lu\n", result);
+  }
+  return result;
+}
+
+#endif /* i586 */
+
+#if defined(__sun) && defined(i586)
+
+/* The definition of a server-class machine for solaris-i586/amd64 */
+jboolean
+solaris_i586_ServerClassMachine(void) {
+  jboolean            result            = JNI_FALSE;
+  /* How big is a server class machine? */
+  const unsigned long server_processors = 2UL;
+  const uint64_t      server_memory     = 2UL * GB;
+  /*
+   * We seem not to get our full complement of memory.
+   *     We allow some part (1/8?) of the memory to be "missing",
+   *     based on the sizes of DIMMs, and maybe graphics cards.
+   */
+  const uint64_t      missing_memory    = 256UL * MB;
+  const uint64_t      actual_memory     = physical_memory();
+
+  /* Is this a server class machine? */
+  if (actual_memory >= (server_memory - missing_memory)) {
+    const unsigned long actual_processors = physical_processors();
+    if (actual_processors >= server_processors) {
+      result = JNI_TRUE;
+    }
+  }
+  if (_launcher_debug) {
+    printf("solaris_" LIBARCHNAME "_ServerClassMachine: %s\n",
+           (result == JNI_TRUE ? "true" : "false"));
+  }
+  return result;
+}
+
+#endif /* __sun && i586 */
+
+#if defined(__linux__) && defined(i586)
+
+/* The definition of a server-class machine for linux-i586 */
+jboolean
+linux_i586_ServerClassMachine(void) {
+  jboolean            result            = JNI_FALSE;
+  /* How big is a server class machine? */
+  const unsigned long server_processors = 2UL;
+  const uint64_t      server_memory     = 2UL * GB;
+  /*
+   * We seem not to get our full complement of memory.
+   *     We allow some part (1/8?) of the memory to be "missing",
+   *     based on the sizes of DIMMs, and maybe graphics cards.
+   */
+  const uint64_t      missing_memory    = 256UL * MB;
+  const uint64_t      actual_memory     = physical_memory();
+
+  /* Is this a server class machine? */
+  if (actual_memory >= (server_memory - missing_memory)) {
+    const unsigned long actual_processors = physical_processors();
+    if (actual_processors >= server_processors) {
+      result = JNI_TRUE;
+    }
+  }
+  if (_launcher_debug) {
+    printf("linux_" LIBARCHNAME "_ServerClassMachine: %s\n",
+           (result == JNI_TRUE ? "true" : "false"));
+  }
+  return result;
+}
+
+#endif /* __linux__ && i586 */
+
+/* Dispatch to the platform-specific definition of "server-class" */
+jboolean
+ServerClassMachine(void) {
+  jboolean result = JNI_FALSE;
+#if   defined(NEVER_ACT_AS_SERVER_CLASS_MACHINE)
+  result = JNI_FALSE;
+#elif defined(ALWAYS_ACT_AS_SERVER_CLASS_MACHINE)
+  result = JNI_TRUE;
+#elif defined(__sun) && defined(__sparc)
+  result = solaris_sparc_ServerClassMachine();
+#elif defined(__sun) && defined(i586)
+  result = solaris_i586_ServerClassMachine();
+#elif defined(__linux__) && defined(i586)
+  result = linux_i586_ServerClassMachine();
+#else
+  if (_launcher_debug) {
+    printf("ServerClassMachine: returns default value of %s\n",
+           (result == JNI_TRUE ? "true" : "false"));
+  }
+#endif
+  return result;
+}
+
+/*
+ *      Since using the file system as a registry is a bit risky, perform
+ *      additional sanity checks on the identified directory to validate
+ *      it as a valid jre/sdk.
+ *
+ *      Return 0 if the tests fail; otherwise return non-zero (true).
+ *
+ *      Note that checking for anything more than the existence of an
+ *      executable object at bin/java relative to the path being checked
+ *      will break the regression tests.
+ */
+static int
+CheckSanity(char *path, char *dir)
+{
+    char    buffer[PATH_MAX];
+
+    if (strlen(path) + strlen(dir) + 11 > PATH_MAX)
+        return (0);     /* Silently reject "impossibly" long paths */
+
+    (void)strcat(strcat(strcat(strcpy(buffer, path), "/"), dir), "/bin/java");
+    return ((access(buffer, X_OK) == 0) ? 1 : 0);
+}
+
+/*
+ *      Determine if there is an acceptable JRE in the directory dirname.
+ *      Upon locating the "best" one, return a fully qualified path to
+ *      it. "Best" is defined as the most advanced JRE meeting the
+ *      constraints contained in the manifest_info. If no JRE in this
+ *      directory meets the constraints, return NULL.
+ *
+ *      Note that we don't check for errors in reading the directory
+ *      (which would be done by checking errno).  This is because it
+ *      doesn't matter if we get an error reading the directory, or
+ *      we just don't find anything interesting in the directory.  We
+ *      just return NULL in either case.
+ *
+ *      The historical names of j2sdk and j2re were changed to jdk and
+ *      jre respecively as part of the 1.5 rebranding effort.  Since the
+ *      former names are legacy on Linux, they must be recognized for
+ *      all time.  Fortunately, this is a minor cost.
+ */
+static char
+*ProcessDir(manifest_info *info, char *dirname)
+{
+    DIR     *dirp;
+    struct dirent *dp;
+    char    *best = NULL;
+    int     offset;
+    int     best_offset = 0;
+    char    *ret_str = NULL;
+    char    buffer[PATH_MAX];
+
+    if ((dirp = opendir(dirname)) == NULL)
+        return (NULL);
+
+    do {
+        if ((dp = readdir(dirp)) != NULL) {
+            offset = 0;
+            if ((strncmp(dp->d_name, "jre", 3) == 0) ||
+                (strncmp(dp->d_name, "jdk", 3) == 0))
+                offset = 3;
+            else if (strncmp(dp->d_name, "j2re", 4) == 0)
+                offset = 4;
+            else if (strncmp(dp->d_name, "j2sdk", 5) == 0)
+                offset = 5;
+            if (offset > 0) {
+                if ((JLI_AcceptableRelease(dp->d_name + offset,
+                    info->jre_version)) && CheckSanity(dirname, dp->d_name))
+                    if ((best == NULL) || (JLI_ExactVersionId(
+                      dp->d_name + offset, best + best_offset) > 0)) {
+                        if (best != NULL)
+                            JLI_MemFree(best);
+                        best = JLI_StringDup(dp->d_name);
+                        best_offset = offset;
+                    }
+            }
+        }
+    } while (dp != NULL);
+    (void) closedir(dirp);
+    if (best == NULL)
+        return (NULL);
+    else {
+        ret_str = JLI_MemAlloc(strlen(dirname) + strlen(best) + 2);
+        ret_str = strcat(strcat(strcpy(ret_str, dirname), "/"), best);
+        JLI_MemFree(best);
+        return (ret_str);
+    }
+}
+
+/*
+ *      This is the global entry point. It examines the host for the optimal
+ *      JRE to be used by scanning a set of directories.  The set of directories
+ *      is platform dependent and can be overridden by the environment
+ *      variable JAVA_VERSION_PATH.
+ *
+ *      This routine itself simply determines the set of appropriate
+ *      directories before passing control onto ProcessDir().
+ */
+char*
+LocateJRE(manifest_info* info)
+{
+    char        *path;
+    char        *home;
+    char        *target = NULL;
+    char        *dp;
+    char        *cp;
+
+    /*
+     * Start by getting JAVA_VERSION_PATH
+     */
+    if (info->jre_restrict_search)
+        path = JLI_StringDup(system_dir);
+    else if ((path = getenv("JAVA_VERSION_PATH")) != NULL)
+        path = JLI_StringDup(path);
+    else
+        if ((home = getenv("HOME")) != NULL) {
+            path = (char *)JLI_MemAlloc(strlen(home) + strlen(system_dir) +
+                strlen(user_dir) + 2);
+            path = strcat(strcat(strcat(strcpy(path, home),
+                user_dir), ":"), system_dir);
+        } else
+            path = JLI_StringDup(system_dir);
+
+    /*
+     * Step through each directory on the path. Terminate the scan with
+     * the first directory with an acceptable JRE.
+     */
+    cp = dp = path;
+    while (dp != NULL) {
+        cp = strchr(dp, (int)':');
+        if (cp != NULL)
+            *cp = (char)NULL;
+        if ((target = ProcessDir(info, dp)) != NULL)
+            break;
+        dp = cp;
+        if (dp != NULL)
+            dp++;
+    }
+    JLI_MemFree(path);
+    return (target);
+}
+
+/*
+ * Given a path to a jre to execute, this routine checks if this process
+ * is indeed that jre.  If not, it exec's that jre.
+ *
+ * We want to actually check the paths rather than just the version string
+ * built into the executable, so that given version specification (and
+ * JAVA_VERSION_PATH) will yield the exact same Java environment, regardless
+ * of the version of the arbitrary launcher we start with.
+ */
+void
+ExecJRE(char *jre, char **argv)
+{
+    char    wanted[PATH_MAX];
+    char    *execname;
+    char    *progname;
+
+    /*
+     * Resolve the real path to the directory containing the selected JRE.
+     */
+    if (realpath(jre, wanted) == NULL) {
+        fprintf(stderr, "Unable to resolve %s\n", jre);
+        exit(1);
+    }
+
+    /*
+     * Resolve the real path to the currently running launcher.
+     */
+    execname = SetExecname(argv);
+    if (execname == NULL) {
+        fprintf(stderr, "Unable to resolve current executable\n");
+        exit(1);
+    }
+
+    /*
+     * If the path to the selected JRE directory is a match to the initial
+     * portion of the path to the currently executing JRE, we have a winner!
+     * If so, just return.
+     */
+    if (strncmp(wanted, execname, strlen(wanted)) == 0)
+        return;                 /* I am the droid you were looking for */
+
+    /*
+     * If this isn't the selected version, exec the selected version.
+     */
+#ifdef JAVA_ARGS  /* javac, jar and friends. */
+    progname = "java";
+#else             /* java, oldjava, javaw and friends */
+#ifdef PROGNAME
+    progname = PROGNAME;
+#else
+    progname = *argv;
+    if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) {
+        progname = s + 1;
+    }
+#endif /* PROGNAME */
+#endif /* JAVA_ARGS */
+
+    /*
+     * This should never happen (because of the selection code in SelectJRE),
+     * but check for "impossibly" long path names just because buffer overruns
+     * can be so deadly.
+     */
+    if (strlen(wanted) + strlen(progname) + 6 > PATH_MAX) {
+        fprintf(stderr, "Path length exceeds maximum length (PATH_MAX)\n");
+        exit(1);
+    }
+
+    /*
+     * Construct the path and exec it.
+     */
+    (void)strcat(strcat(wanted, "/bin/"), progname);
+    argv[0] = progname;
+    if (_launcher_debug) {
+        int i;
+        printf("ReExec Command: %s (%s)\n", wanted, argv[0]);
+        printf("ReExec Args:");
+        for (i = 1; argv[i] != NULL; i++)
+            printf(" %s", argv[i]);
+        printf("\n");
+    }
+    (void)fflush(stdout);
+    (void)fflush(stderr);
+    execv(wanted, argv);
+    perror("execv()");
+    fprintf(stderr, "Exec of %s failed\n", wanted);
+    exit(1);
+}
+#endif /* ifndef GAMMA */
+
+/*
+ * "Borrowed" from Solaris 10 where the unsetenv() function is being added
+ * to libc thanks to SUSv3 (Standard Unix Specification, version 3). As
+ * such, in the fullness of time this will appear in libc on all relevant
+ * Solaris/Linux platforms and maybe even the Windows platform.  At that
+ * time, this stub can be removed.
+ *
+ * This implementation removes the environment locking for multithreaded
+ * applications.  (We don't have access to these mutexes within libc and
+ * the launcher isn't multithreaded.)  Note that what remains is platform
+ * independent, because it only relies on attributes that a POSIX environment
+ * defines.
+ *
+ * Returns 0 on success, -1 on failure.
+ *
+ * Also removed was the setting of errno.  The only value of errno set
+ * was EINVAL ("Invalid Argument").
+ */
+
+/*
+ * s1(environ) is name=value
+ * s2(name) is name(not the form of name=value).
+ * if names match, return value of 1, else return 0
+ */
+static int
+match_noeq(const char *s1, const char *s2)
+{
+        while (*s1 == *s2++) {
+                if (*s1++ == '=')
+                        return (1);
+        }
+        if (*s1 == '=' && s2[-1] == '\0')
+                return (1);
+        return (0);
+}
+
+/*
+ * added for SUSv3 standard
+ *
+ * Delete entry from environ.
+ * Do not free() memory!  Other threads may be using it.
+ * Keep it around forever.
+ */
+static int
+borrowed_unsetenv(const char *name)
+{
+        long    idx;            /* index into environ */
+
+        if (name == NULL || *name == '\0' ||
+            strchr(name, '=') != NULL) {
+                return (-1);
+        }
+
+        for (idx = 0; environ[idx] != NULL; idx++) {
+                if (match_noeq(environ[idx], name))
+                        break;
+        }
+        if (environ[idx] == NULL) {
+                /* name not found but still a success */
+                return (0);
+        }
+        /* squeeze up one entry */
+        do {
+                environ[idx] = environ[idx+1];
+        } while (environ[++idx] != NULL);
+
+        return (0);
+}
+/* --- End of "borrowed" code --- */
+
+/*
+ * Wrapper for unsetenv() function.
+ */
+int
+UnsetEnv(char *name)
+{
+    return(borrowed_unsetenv(name));
+}
+
+/* --- Splash Screen shared library support --- */
+
+static const char* SPLASHSCREEN_SO = "libsplashscreen.so";
+
+static void* hSplashLib = NULL;
+
+void* SplashProcAddress(const char* name) {
+    if (!hSplashLib) {
+        hSplashLib = dlopen(SPLASHSCREEN_SO, RTLD_LAZY | RTLD_GLOBAL);
+    }
+    if (hSplashLib) {
+        void* sym = dlsym(hSplashLib, name);
+        return sym;
+    } else {
+        return NULL;
+    }
+}
+
+void SplashFreeLibrary() {
+    if (hSplashLib) {
+        dlclose(hSplashLib);
+        hSplashLib = NULL;
+    }
+}
+
+const char *
+jlong_format_specifier() {
+    return "%lld";
+}
+
+/*
+ * Block current thread and continue execution in a new thread
+ */
+int
+ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void * args) {
+    int rslt;
+#ifdef __linux__
+    pthread_t tid;
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+    if (stack_size > 0) {
+      pthread_attr_setstacksize(&attr, stack_size);
+    }
+
+    if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) {
+      void * tmp;
+      pthread_join(tid, &tmp);
+      rslt = (int)tmp;
+    } else {
+     /*
+      * Continue execution in current thread if for some reason (e.g. out of
+      * memory/LWP)  a new thread can't be created. This will likely fail
+      * later in continuation as JNI_CreateJavaVM needs to create quite a
+      * few new threads, anyway, just give it a try..
+      */
+      rslt = continuation(args);
+    }
+
+    pthread_attr_destroy(&attr);
+#else
+    thread_t tid;
+    long flags = 0;
+    if (thr_create(NULL, stack_size, (void *(*)(void *))continuation, args, flags, &tid) == 0) {
+      void * tmp;
+      thr_join(tid, NULL, &tmp);
+      rslt = (int)tmp;
+    } else {
+      /* See above. Continue in current thread if thr_create() failed */
+      rslt = continuation(args);
+    }
+#endif
+    return rslt;
+}
+
+/* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */
+#define MAX_PID_STR_SZ   20
+
+void SetJavaLauncherPlatformProps() {
+   /* Linux only */
+#ifdef __linux__
+    const char *substr = "-Dsun.java.launcher.pid=";
+    char *pid_prop_str = (char *)JLI_MemAlloc(strlen(substr) + MAX_PID_STR_SZ + 1);
+    sprintf(pid_prop_str, "%s%d", substr, getpid());
+    AddOption(pid_prop_str, NULL);
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/posix/launcher/java_md.h	Thu Dec 02 05:45:54 2010 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef JAVA_MD_H
+#define JAVA_MD_H
+
+#include <limits.h>
+#include <unistd.h>
+#include <sys/param.h>
+#ifndef GAMMA
+#include "manifest_info.h"
+#endif
+#include "jli_util.h"
+
+#define PATH_SEPARATOR          ':'
+#define FILESEP                 "/"
+#define FILE_SEPARATOR          '/'
+#define IS_FILE_SEPARATOR(c) ((c) == '/')
+#ifndef MAXNAMELEN
+#define MAXNAMELEN              PATH_MAX
+#endif
+
+#ifdef JAVA_ARGS
+/*
+ * ApplicationHome is prepended to each of these entries; the resulting
+ * strings are concatenated (separated by PATH_SEPARATOR) and used as the
+ * value of -cp option to the launcher.
+ */
+#ifndef APP_CLASSPATH
+#define APP_CLASSPATH        { "/lib/tools.jar", "/classes" }
+#endif
+#endif
+
+#ifdef HAVE_GETHRTIME
+/*
+ * Support for doing cheap, accurate interval timing.
+ */
+#include <sys/time.h>
+#define CounterGet()              (gethrtime()/1000)
+#define Counter2Micros(counts)    (counts)
+#else
+#define CounterGet()              (0)
+#define Counter2Micros(counts)    (1)
+#endif /* HAVE_GETHRTIME */
+
+/*
+ * Function prototypes.
+ */
+#ifndef GAMMA
+char *LocateJRE(manifest_info *info);
+void ExecJRE(char *jre, char **argv);
+#endif
+int UnsetEnv(char *name);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/posix/launcher/launcher.script	Thu Dec 02 05:45:54 2010 -0800
@@ -0,0 +1,208 @@
+#!/bin/bash
+
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+
+
+# This script launches HotSpot.
+#
+# If the first parameter is either "-gdb" or "-gud", HotSpot will be
+# launched inside gdb. "-gud" means "open an Emacs window and run gdb
+# inside Emacs".
+#
+# If the first parameter is "-dbx", HotSpot will be launched inside dbx.
+# 
+# If the first parameter is "-valgrind", HotSpot will be launched
+# inside Valgrind (http://valgrind.kde.org) using the Memcheck skin,
+# and with memory leak detection enabled.  This currently (2005jan19)
+# requires at least Valgrind 2.3.0.  -Xmx16m will also be passed as
+# the first parameter to HotSpot, since lowering HotSpot's memory
+# consumption makes execution inside of Valgrind *a lot* faster.
+#
+
+
+#
+# User changeable parameters ------------------------------------------------
+#
+
+# This is the name of the gdb binary to use
+if [ ! "$GDB" ]
+then 
+    GDB=gdb
+fi
+
+# This is the name of the gdb binary to use
+if [ ! "$DBX" ]
+then 
+    DBX=dbx
+fi
+
+# This is the name of the Valgrind binary to use
+if [ ! "$VALGRIND" ]
+then 
+    VALGRIND=valgrind
+fi
+
+# This is the name of Emacs for running GUD
+EMACS=emacs
+
+#
+# End of user changeable parameters -----------------------------------------
+#
+
+# Make sure the paths are fully specified, i.e. they must begin with /.
+SCRIPT=$(cd $(dirname $0) && pwd)/$(basename $0)
+RUNDIR=$(pwd)
+
+# Look whether the user wants to run inside gdb
+case "$1" in
+    -gdb)
+        MODE=gdb
+        shift
+        ;;
+    -gud)
+        MODE=gud
+        shift
+        ;;
+    -dbx)
+        MODE=dbx
+        shift
+        ;;
+    -valgrind)
+        MODE=valgrind
+        shift
+        ;;
+    *)
+        MODE=run
+        ;;
+esac
+
+if [ "${ALT_JAVA_HOME}" = "" ]; then
+    if [ "${JAVA_HOME}" = "" ]; then
+	echo "Neither ALT_JAVA_HOME nor JAVA_HOME is set. Aborting.";
+	exit 1;
+    else
+	JDK=${JAVA_HOME%%/jre};
+    fi
+else 
+    JDK=${ALT_JAVA_HOME%%/jre};
+fi
+
+# We will set the LD_LIBRARY_PATH as follows:
+#     o		$JVMPATH (directory portion only)
+#     o		$JRE/lib/$ARCH
+# followed by the user's previous effective LD_LIBRARY_PATH, if
+# any.
+JRE=$JDK/jre
+JAVA_HOME=$JDK
+ARCH=@@LIBARCH@@
+
+# Find out the absolute path to this script
+MYDIR=$(cd $(dirname $SCRIPT) && pwd)
+
+SBP=${MYDIR}:${JRE}/lib/${ARCH}
+
+# Set up a suitable LD_LIBRARY_PATH
+
+if [ -z "$LD_LIBRARY_PATH" ]
+then
+    LD_LIBRARY_PATH="$SBP"
+else
+    LD_LIBRARY_PATH="$SBP:$LD_LIBRARY_PATH"
+fi
+
+export LD_LIBRARY_PATH
+export JAVA_HOME
+
+JPARMS="$@ $JAVA_ARGS";
+
+# Locate the gamma development launcher
+LAUNCHER=${MYDIR}/gamma
+if [ ! -x $LAUNCHER ] ; then
+    echo Error: Cannot find the gamma development launcher \"$LAUNCHER\"
+    exit 1
+fi
+
+GDBSRCDIR=$MYDIR
+BASEDIR=$(cd $MYDIR/../../.. && pwd)
+
+init_gdb() {
+# Create a gdb script in case we should run inside gdb
+    GDBSCR=/tmp/hsl.$$
+    rm -f $GDBSCR
+    cat >>$GDBSCR <<EOF
+cd `pwd`
+handle SIGUSR1 nostop noprint
+handle SIGUSR2 nostop noprint
+set args $JPARMS
+file $LAUNCHER
+directory $GDBSRCDIR
+# Get us to a point where we can set breakpoints in libjvm.so
+break InitializeJVM
+run
+# Stop in InitializeJVM
+delete 1
+# We can now set breakpoints wherever we like
+EOF
+}
+
+
+case "$MODE" in
+    gdb)
+	init_gdb
+        $GDB -x $GDBSCR
+	rm -f $GDBSCR
+        ;;
+    gud)
+	init_gdb
+# First find out what emacs version we're using, so that we can
+# use the new pretty GDB mode if emacs -version >= 22.1
+	case $($EMACS -version 2> /dev/null) in
+	    *GNU\ Emacs\ 2[23]*)
+	    emacs_gud_cmd="gdba"
+	    emacs_gud_args="--annotate=3"
+	    ;;
+	    *)
+		emacs_gud_cmd="gdb"
+		emacs_gud_args=
+		;;
+	esac
+        $EMACS --eval "($emacs_gud_cmd \"$GDB $emacs_gud_args -x $GDBSCR\")";
+	rm -f $GDBSCR
+        ;;
+    dbx)
+        $DBX -s $MYDIR/.dbxrc $LAUNCHER $JPARAMS
+        ;;
+    valgrind)
+        echo Warning: Defaulting to 16Mb heap to make Valgrind run faster, use -Xmx for larger heap
+        echo
+        $VALGRIND --tool=memcheck --leak-check=yes --num-callers=50 $LAUNCHER -Xmx16m $JPARMS
+        ;;
+    run)
+        LD_PRELOAD=$PRELOADING exec $LAUNCHER $JPARMS
+        ;;
+    *)
+        echo Error: Internal error, unknown launch mode \"$MODE\"
+        exit 1
+        ;;
+esac
+RETVAL=$?
+exit $RETVAL
--- a/hotspot/src/os/solaris/launcher/java.c	Thu Dec 02 20:01:47 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1842 +0,0 @@
-/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK,
- * search "GAMMA" for gamma specific changes.
- *
- * GAMMA: gamma launcher is much simpler than regular java launcher in that
- *        JVM is either statically linked in or it is installed in the
- *        same directory where the launcher exists, so we don't have to
- *        worry about choosing the right JVM based on command line flag, jar
- *        file and/or ergonomics. Intead of removing unused logic from source
- *        they are commented out with #ifndef GAMMA, hopefully it'll be easier
- *        to maintain this file in sync with regular JDK launcher.
- */
-
-/*
- * Shared source for 'java' command line tool.
- *
- * If JAVA_ARGS is defined, then acts as a launcher for applications. For
- * instance, the JDK command line tools such as javac and javadoc (see
- * makefiles for more details) are built with this program.  Any arguments
- * prefixed with '-J' will be passed directly to the 'java' command.
- */
-
-#ifdef GAMMA
-#  ifdef JAVA_ARGS
-#    error Do NOT define JAVA_ARGS when building gamma launcher
-#  endif
-#  if !defined(LINK_INTO_AOUT) && !defined(LINK_INTO_LIBJVM)
-#    error Either LINK_INTO_AOUT or LINK_INTO_LIBJVM must be defined
-#  endif
-#endif
-
-/*
- * One job of the launcher is to remove command line options which the
- * vm does not understand and will not process.  These options include
- * options which select which style of vm is run (e.g. -client and
- * -server) as well as options which select the data model to use.
- * Additionally, for tools which invoke an underlying vm "-J-foo"
- * options are turned into "-foo" options to the vm.  This option
- * filtering is handled in a number of places in the launcher, some of
- * it in machine-dependent code.  In this file, the function
- * CheckJVMType removes vm style options and TranslateDashJArgs
- * removes "-J" prefixes.  On unix platforms, the
- * CreateExecutionEnvironment function from the unix java_md.c file
- * processes and removes -d<n> options.  However, in case
- * CreateExecutionEnvironment does not need to exec because
- * LD_LIBRARY_PATH is set acceptably and the data model does not need
- * to be changed, ParseArguments will screen out the redundant -d<n>
- * options and prevent them from being passed to the vm; this is done
- * by using the machine-dependent call
- * RemovableMachineDependentOption.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <jni.h>
-#include "java.h"
-
-#ifndef GAMMA
-#include "manifest_info.h"
-#include "version_comp.h"
-#endif
-
-#ifndef FULL_VERSION
-#define FULL_VERSION JDK_MAJOR_VERSION "." JDK_MINOR_VERSION
-#endif
-
-/*
- * The following environment variable is used to influence the behavior
- * 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
- * to take precedence.
- *
- * 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
- * interfaces.
- */
-#define ENV_ENTRY "_JAVA_VERSION_SET"
-
-static jboolean printVersion = JNI_FALSE; /* print and exit */
-static jboolean showVersion = JNI_FALSE;  /* print but continue */
-static char *progname;
-jboolean _launcher_debug = JNI_FALSE;
-
-/*
- * List of VM options to be specified when the VM is created.
- */
-static JavaVMOption *options;
-static int numOptions, maxOptions;
-
-/*
- * Prototypes for functions internal to launcher.
- */
-static void AddOption(char *str, void *info);
-static void SetClassPath(char *s);
-static void SelectVersion(int argc, char **argv, char **main_class);
-static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile,
-                               char **pclassname, int *pret);
-static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
-                              InvocationFunctions *ifn);
-static jstring NewPlatformString(JNIEnv *env, char *s);
-static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc);
-static jclass LoadClass(JNIEnv *env, char *name);
-static jstring GetMainClassName(JNIEnv *env, char *jarname);
-static void SetJavaCommandLineProp(char* classname, char* jarfile, int argc, char** argv);
-#ifdef GAMMA
-static void SetJavaLauncherProp(void);
-#endif
-
-#ifdef JAVA_ARGS
-static void TranslateDashJArgs(int *pargc, char ***pargv);
-static jboolean AddApplicationOptions(void);
-#endif
-
-static void PrintJavaVersion(JNIEnv *env);
-static void PrintUsage(void);
-static jint PrintXUsage(void);
-
-static void SetPaths(int argc, char **argv);
-
-/* Maximum supported entries from jvm.cfg. */
-#define INIT_MAX_KNOWN_VMS      10
-/* Values for vmdesc.flag */
-#define VM_UNKNOWN              -1
-#define VM_KNOWN                 0
-#define VM_ALIASED_TO            1
-#define VM_WARN                  2
-#define VM_ERROR                 3
-#define VM_IF_SERVER_CLASS       4
-#define VM_IGNORE                5
-struct vmdesc {
-    char *name;
-    int flag;
-    char *alias;
-    char *server_class;
-};
-static struct vmdesc *knownVMs = NULL;
-static int knownVMsCount = 0;
-static int knownVMsLimit = 0;
-
-static void GrowKnownVMs();
-static int  KnownVMIndex(const char* name);
-static void FreeKnownVMs();
-
-jboolean ServerClassMachine();
-
-/* flag which if set suppresses error messages from the launcher */
-static int noExitErrorMessage = 0;
-
-/*
- * Entry point.
- */
-int
-main(int argc, char ** argv)
-{
-    JavaVM *vm = 0;
-    JNIEnv *env = 0;
-    char *jarfile = 0;
-    char *classname = 0;
-    char *s = 0;
-    char *main_class = NULL;
-    jstring mainClassName;
-    jclass mainClass;
-    jmethodID mainID;
-    jobjectArray mainArgs;
-    int ret;
-    InvocationFunctions ifn;
-    jlong start, end;
-    char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN];
-    char ** original_argv = argv;
-
-    /*
-     * 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.";
-    jboolean messageDest = JNI_FALSE;
-
-    if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) {
-        _launcher_debug = JNI_TRUE;
-        printf("----_JAVA_LAUNCHER_DEBUG----\n");
-    }
-
-#ifndef GAMMA
-    /*
-     * 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
-     *     was issued).
-     *  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
-     *     bugid 5030265 below.)
-     */
-    SelectVersion(argc, argv, &main_class);
-#endif /* ifndef GAMMA */
-
-    /* copy original argv */
-    {
-      int i;
-      original_argv = (char**)MemAlloc(sizeof(char*)*(argc+1));
-      for(i = 0; i < argc+1; i++)
-        original_argv[i] = argv[i];
-    }
-
-    CreateExecutionEnvironment(&argc, &argv,
-                               jrepath, sizeof(jrepath),
-                               jvmpath, sizeof(jvmpath),
-                               original_argv);
-    ifn.CreateJavaVM = 0;
-    ifn.GetDefaultJavaVMInitArgs = 0;
-
-    if (_launcher_debug)
-      start = CounterGet();
-    if (!LoadJavaVM(jvmpath, &ifn)) {
-      exit(6);
-    }
-    if (_launcher_debug) {
-      end   = CounterGet();
-      printf("%ld micro seconds to LoadJavaVM\n",
-             (long)(jint)Counter2Micros(end-start));
-    }
-
-#ifdef JAVA_ARGS  /* javac, jar and friends. */
-    progname = "java";
-#else             /* java, oldjava, javaw and friends */
-#ifdef PROGNAME
-    progname = PROGNAME;
-#else
-    progname = *argv;
-    if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) {
-        progname = s + 1;
-    }
-#endif /* PROGNAME */
-#endif /* JAVA_ARGS */
-    ++argv;
-    --argc;
-
-#ifdef JAVA_ARGS
-    /* Preprocess wrapper arguments */
-    TranslateDashJArgs(&argc, &argv);
-    if (!AddApplicationOptions()) {
-        exit(1);
-    }
-#endif
-
-    /* Set default CLASSPATH */
-    if ((s = getenv("CLASSPATH")) == 0) {
-        s = ".";
-    }
-#ifndef JAVA_ARGS
-    SetClassPath(s);
-#endif
-
-    /*
-     *  Parse command line options; if the return value of
-     *  ParseArguments is false, the program should exit.
-     */
-    if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret)) {
-      exit(ret);
-    }
-
-    /* Override class path if -jar flag was specified */
-    if (jarfile != 0) {
-        SetClassPath(jarfile);
-    }
-
-    /* set the -Dsun.java.command pseudo property */
-    SetJavaCommandLineProp(classname, jarfile, argc, argv);
-
-#ifdef GAMMA
-    /* Set the -Dsun.java.launcher pseudo property */
-    SetJavaLauncherProp();
-#endif
-
-    /*
-     * Done with all command line processing and potential re-execs so
-     * clean up the environment.
-     */
-    (void)UnsetEnv(ENV_ENTRY);
-
-    /* Initialize the virtual machine */
-
-    if (_launcher_debug)
-        start = CounterGet();
-    if (!InitializeJVM(&vm, &env, &ifn)) {
-        ReportErrorMessage("Could not create the Java virtual machine.",
-                           JNI_TRUE);
-        exit(1);
-    }
-
-    if (printVersion || showVersion) {
-        PrintJavaVersion(env);
-        if ((*env)->ExceptionOccurred(env)) {
-            ReportExceptionDescription(env);
-            goto leave;
-        }
-        if (printVersion) {
-            ret = 0;
-            message = NULL;
-            goto leave;
-        }
-        if (showVersion) {
-            fprintf(stderr, "\n");
-        }
-    }
-
-    /* If the user specified neither a class name nor a JAR file */
-    if (jarfile == 0 && classname == 0) {
-        PrintUsage();
-        message = NULL;
-        goto leave;
-    }
-
-#ifndef GAMMA
-    FreeKnownVMs();  /* after last possible PrintUsage() */
-#endif
-
-    if (_launcher_debug) {
-        end   = CounterGet();
-        printf("%ld micro seconds to InitializeJVM\n",
-               (long)(jint)Counter2Micros(end-start));
-    }
-
-    /* At this stage, argc/argv have the applications' arguments */
-    if (_launcher_debug) {
-        int i = 0;
-        printf("Main-Class is '%s'\n", classname ? classname : "");
-        printf("Apps' argc is %d\n", argc);
-        for (; i < argc; i++) {
-            printf("    argv[%2d] = '%s'\n", i, argv[i]);
-        }
-    }
-
-    ret = 1;
-
-    /*
-     * 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
-     *          all environments,
-     *     2)   Remove the vestages of maintaining main_class through
-     *          the environment (and remove these comments).
-     */
-    if (jarfile != 0) {
-        mainClassName = GetMainClassName(env, jarfile);
-        if ((*env)->ExceptionOccurred(env)) {
-            ReportExceptionDescription(env);
-            goto leave;
-        }
-        if (mainClassName == NULL) {
-          const char * format = "Failed to load Main-Class manifest "
-                                "attribute from\n%s";
-          message = (char*)MemAlloc((strlen(format) + strlen(jarfile)) *
-                                    sizeof(char));
-          sprintf(message, format, jarfile);
-          messageDest = JNI_TRUE;
-          goto leave;
-        }
-        classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
-        if (classname == NULL) {
-            ReportExceptionDescription(env);
-            goto leave;
-        }
-        mainClass = LoadClass(env, classname);
-        if(mainClass == NULL) { /* exception occurred */
-            ReportExceptionDescription(env);
-            message = "Could not find the main class.  Program will exit.";
-            goto leave;
-        }
-        (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
-    } else {
-      mainClassName = NewPlatformString(env, classname);
-      if (mainClassName == NULL) {
-        const char * format = "Failed to load Main Class: %s";
-        message = (char *)MemAlloc((strlen(format) + strlen(classname)) *
-                                   sizeof(char) );
-        sprintf(message, format, classname);
-        messageDest = JNI_TRUE;
-        goto leave;
-      }
-      classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
-      if (classname == NULL) {
-        ReportExceptionDescription(env);
-        goto leave;
-      }
-      mainClass = LoadClass(env, classname);
-      if(mainClass == NULL) { /* exception occurred */
-        ReportExceptionDescription(env);
-        message = "Could not find the main class. Program will exit.";
-        goto leave;
-      }
-      (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
-    }
-
-    /* Get the application's main method */
-    mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
-                                       "([Ljava/lang/String;)V");
-    if (mainID == NULL) {
-        if ((*env)->ExceptionOccurred(env)) {
-            ReportExceptionDescription(env);
-        } else {
-          message = "No main method found in specified class.";
-          messageDest = JNI_TRUE;
-        }
-        goto leave;
-    }
-
-    {    /* Make sure the main method is public */
-        jint mods;
-        jmethodID mid;
-        jobject obj = (*env)->ToReflectedMethod(env, mainClass,
-                                                mainID, JNI_TRUE);
-
-        if( obj == NULL) { /* exception occurred */
-            ReportExceptionDescription(env);
-            goto leave;
-        }
-
-        mid =
-          (*env)->GetMethodID(env,
-                              (*env)->GetObjectClass(env, obj),
-                              "getModifiers", "()I");
-        if ((*env)->ExceptionOccurred(env)) {
-            ReportExceptionDescription(env);
-            goto leave;
-        }
-
-        mods = (*env)->CallIntMethod(env, obj, mid);
-        if ((mods & 1) == 0) { /* if (!Modifier.isPublic(mods)) ... */
-            message = "Main method not public.";
-            messageDest = JNI_TRUE;
-            goto leave;
-        }
-    }
-
-    /* Build argument array */
-    mainArgs = NewPlatformStringArray(env, argv, argc);
-    if (mainArgs == NULL) {
-        ReportExceptionDescription(env);
-        goto leave;
-    }
-
-    /* Invoke main method. */
-    (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
-
-    /*
-     * The launcher's exit code (in the absence of calls to
-     * System.exit) will be non-zero if main threw an exception.
-     */
-    ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
-
-    /*
-     * 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.
-     */
-    if ((*vm)->DetachCurrentThread(vm) != 0) {
-        message = "Could not detach main thread.";
-        messageDest = JNI_TRUE;
-        ret = 1;
-        goto leave;
-    }
-
-    message = NULL;
-
- leave:
-    /*
-     * 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.
-     */
-    (*vm)->DestroyJavaVM(vm);
-
-    if(message != NULL && !noExitErrorMessage)
-      ReportErrorMessage(message, messageDest);
-    return ret;
-}
-
-
-#ifndef GAMMA
-/*
- * 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.
- */
-char *
-CheckJvmType(int *pargc, char ***argv, jboolean speculative) {
-    int i, argi;
-    int argc;
-    char **newArgv;
-    int newArgvIdx = 0;
-    int isVMType;
-    int jvmidx = -1;
-    char *jvmtype = getenv("JDK_ALTERNATE_VM");
-
-    argc = *pargc;
-
-    /* To make things simpler we always copy the argv array */
-    newArgv = MemAlloc((argc + 1) * sizeof(char *));
-
-    /* The program name is always present */
-    newArgv[newArgvIdx++] = (*argv)[0];
-
-    for (argi = 1; argi < argc; argi++) {
-        char *arg = (*argv)[argi];
-        isVMType = 0;
-
-#ifdef JAVA_ARGS
-        if (arg[0] != '-') {
-            newArgv[newArgvIdx++] = arg;
-            continue;
-        }
-#else
-        if (strcmp(arg, "-classpath") == 0 ||
-            strcmp(arg, "-cp") == 0) {
-            newArgv[newArgvIdx++] = arg;
-            argi++;
-            if (argi < argc) {
-                newArgv[newArgvIdx++] = (*argv)[argi];
-            }
-            continue;
-        }
-        if (arg[0] != '-') break;
-#endif
-
-        /* Did the user pass an explicit VM type? */
-        i = KnownVMIndex(arg);
-        if (i >= 0) {
-            jvmtype = knownVMs[jvmidx = i].name + 1; /* skip the - */
-            isVMType = 1;
-            *pargc = *pargc - 1;
-        }
-
-        /* Did the user specify an "alternate" VM? */
-        else if (strncmp(arg, "-XXaltjvm=", 10) == 0 || strncmp(arg, "-J-XXaltjvm=", 12) == 0) {
-            isVMType = 1;
-            jvmtype = arg+((arg[1]=='X')? 10 : 12);
-            jvmidx = -1;
-        }
-
-        if (!isVMType) {
-            newArgv[newArgvIdx++] = arg;
-        }
-    }
-
-    /*
-     * 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
-     * argc.
-     */
-    while (argi < argc) {
-        newArgv[newArgvIdx++] = (*argv)[argi];
-        argi++;
-    }
-
-    /* argv is null-terminated */
-    newArgv[newArgvIdx] = 0;
-
-    /* Copy back argv */
-    *argv = newArgv;
-    *pargc = newArgvIdx;
-
-    /* use the default VM type if not specified (no alias processing) */
-    if (jvmtype == NULL) {
-      char* result = knownVMs[0].name+1;
-      /* Use a different VM type if we are on a server class machine? */
-      if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) &&
-          (ServerClassMachine() == JNI_TRUE)) {
-        result = knownVMs[0].server_class+1;
-      }
-      if (_launcher_debug) {
-        printf("Default VM: %s\n", result);
-      }
-      return result;
-    }
-
-    /* if using an alternate VM, no alias processing */
-    if (jvmidx < 0)
-      return jvmtype;
-
-    /* Resolve aliases first */
-    {
-      int loopCount = 0;
-      while (knownVMs[jvmidx].flag == VM_ALIASED_TO) {
-        int nextIdx = KnownVMIndex(knownVMs[jvmidx].alias);
-
-        if (loopCount > knownVMsCount) {
-          if (!speculative) {
-            ReportErrorMessage("Error: Corrupt jvm.cfg file; cycle in alias list.",
-                               JNI_TRUE);
-            exit(1);
-          } else {
-            return "ERROR";
-            /* break; */
-          }
-        }
-
-        if (nextIdx < 0) {
-          if (!speculative) {
-            ReportErrorMessage2("Error: Unable to resolve VM alias %s",
-                                knownVMs[jvmidx].alias, JNI_TRUE);
-            exit(1);
-          } else {
-            return "ERROR";
-          }
-        }
-        jvmidx = nextIdx;
-        jvmtype = knownVMs[jvmidx].name+1;
-        loopCount++;
-      }
-    }
-
-    switch (knownVMs[jvmidx].flag) {
-    case VM_WARN:
-        if (!speculative) {
-            fprintf(stderr, "Warning: %s VM not supported; %s VM will be used\n",
-                    jvmtype, knownVMs[0].name + 1);
-        }
-        /* fall through */
-    case VM_IGNORE:
-        jvmtype = knownVMs[jvmidx=0].name + 1;
-        /* fall through */
-    case VM_KNOWN:
-        break;
-    case VM_ERROR:
-        if (!speculative) {
-            ReportErrorMessage2("Error: %s VM not supported", jvmtype, JNI_TRUE);
-            exit(1);
-        } else {
-            return "ERROR";
-        }
-    }
-
-    return jvmtype;
-}
-#endif /* ifndef GAMMA */
-
-/*
- * Adds a new VM option with the given given name and value.
- */
-static void
-AddOption(char *str, void *info)
-{
-    /*
-     * Expand options array if needed to accommodate at least one more
-     * VM option.
-     */
-    if (numOptions >= maxOptions) {
-        if (options == 0) {
-            maxOptions = 4;
-            options = MemAlloc(maxOptions * sizeof(JavaVMOption));
-        } else {
-            JavaVMOption *tmp;
-            maxOptions *= 2;
-            tmp = MemAlloc(maxOptions * sizeof(JavaVMOption));
-            memcpy(tmp, options, numOptions * sizeof(JavaVMOption));
-            free(options);
-            options = tmp;
-        }
-    }
-    options[numOptions].optionString = str;
-    options[numOptions++].extraInfo = info;
-}
-
-static void
-SetClassPath(char *s)
-{
-    char *def = MemAlloc(strlen(s) + 40);
-    sprintf(def, "-Djava.class.path=%s", s);
-    AddOption(def, NULL);
-}
-
-#ifndef GAMMA
-/*
- * 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.
- */
-static void
-SelectVersion(int argc, char **argv, char **main_class)
-{
-    char    *arg;
-    char    **new_argv;
-    char    **new_argp;
-    char    *operand;
-    char    *version = NULL;
-    char    *jre = NULL;
-    int     jarflag = 0;
-    int     restrict_search = -1;               /* -1 implies not known */
-    manifest_info info;
-    char    env_entry[MAXNAMELEN + 24] = ENV_ENTRY "=";
-    char    *env_in;
-    int     res;
-
-    /*
-     * If the version has already been selected, set *main_class
-     * with the value passed through the environment (if any) and
-     * simply return.
-     */
-    if ((env_in = getenv(ENV_ENTRY)) != NULL) {
-        if (*env_in != '\0')
-            *main_class = strdup(env_in);
-        return;
-    }
-
-    /*
-     * Scan through the arguments for options relevant to multiple JRE
-     * support.  For reference, the command line syntax is defined as:
-     *
-     * SYNOPSIS
-     *      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.
-     */
-    new_argv = MemAlloc((argc + 1) * sizeof(char*));
-    new_argv[0] = argv[0];
-    new_argp = &new_argv[1];
-    argc--;
-    argv++;
-    while ((arg = *argv) != 0 && *arg == '-') {
-        if (strncmp(arg, "-version:", 9) == 0) {
-            version = arg + 9;
-        } else if (strcmp(arg, "-jre-restrict-search") == 0) {
-            restrict_search = 1;
-        } else if (strcmp(arg, "-no-jre-restrict-search") == 0) {
-            restrict_search = 0;
-        } else {
-            if (strcmp(arg, "-jar") == 0)
-                jarflag = 1;
-            /* deal with "unfortunate" classpath syntax */
-            if ((strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) &&
-              (argc >= 2)) {
-                *new_argp++ = arg;
-                argc--;
-                argv++;
-                arg = *argv;
-            }
-            *new_argp++ = arg;
-        }
-        argc--;
-        argv++;
-    }
-    if (argc <= 0) {    /* No operand? Possibly legit with -[full]version */
-        operand = NULL;
-    } else {
-        argc--;
-        *new_argp++ = operand = *argv++;
-    }
-    while (argc-- > 0)  /* Copy over [argument...] */
-        *new_argp++ = *argv++;
-    *new_argp = NULL;
-
-    /*
-     * 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
-     * this data around.
-     */
-    if (jarflag && operand) {
-        if ((res = parse_manifest(operand, &info)) != 0) {
-            if (res == -1)
-                ReportErrorMessage2("Unable to access jarfile %s",
-                  operand, JNI_TRUE);
-            else
-                ReportErrorMessage2("Invalid or corrupt jarfile %s",
-                  operand, JNI_TRUE);
-            exit(1);
-        }
-    } else {
-        info.manifest_version = NULL;
-        info.main_class = NULL;
-        info.jre_version = NULL;
-        info.jre_restrict_search = 0;
-    }
-
-    /*
-     * The JRE-Version and JRE-Restrict-Search values (if any) from the
-     * manifest are overwritten by any specified on the command line.
-     */
-    if (version != NULL)
-        info.jre_version = version;
-    if (restrict_search != -1)
-        info.jre_restrict_search = restrict_search;
-
-    /*
-     * "Valid" returns (other than unrecoverable errors) follow.  Set
-     * main_class as a side-effect of this routine.
-     */
-    if (info.main_class != NULL)
-        *main_class = strdup(info.main_class);
-
-    /*
-     * If no version selection information is found either on the command
-     * line or in the manifest, simply return.
-     */
-    if (info.jre_version == NULL) {
-        free_manifest();
-        free(new_argv);
-        return;
-    }
-
-    /*
-     * Check for correct syntax of the version specification (JSR 56).
-     */
-    if (!valid_version_string(info.jre_version)) {
-        ReportErrorMessage2("Syntax error in version specification \"%s\"",
-          info.jre_version, JNI_TRUE);
-        exit(1);
-    }
-
-    /*
-     * 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
-     * JRE support.
-     */
-    jre = LocateJRE(&info);
-    if (_launcher_debug)
-        printf("JRE-Version = %s, JRE-Restrict-Search = %s Selected = %s\n",
-          (info.jre_version?info.jre_version:"null"),
-          (info.jre_restrict_search?"true":"false"), (jre?jre:"null"));
-    if (jre == NULL) {
-        if (acceptable_release(FULL_VERSION, info.jre_version)) {
-            free_manifest();
-            free(new_argv);
-            return;
-        } else {
-            ReportErrorMessage2(
-              "Unable to locate JRE meeting specification \"%s\"",
-              info.jre_version, JNI_TRUE);
-            exit(1);
-        }
-    }
-
-    /*
-     * 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
-     * times.
-     */
-    if (info.main_class != NULL)
-        (void)strcat(env_entry, info.main_class);
-    (void)putenv(env_entry);
-    ExecJRE(jre, new_argv);
-    free_manifest();
-    free(new_argv);
-    return;
-}
-#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
- * 0 for a normal exit.
- */
-static jboolean
-ParseArguments(int *pargc, char ***pargv, char **pjarfile,
-                       char **pclassname, int *pret)
-{
-    int argc = *pargc;
-    char **argv = *pargv;
-    jboolean jarflag = JNI_FALSE;
-    char *arg;
-
-    *pret = 1;
-    while ((arg = *argv) != 0 && *arg == '-') {
-        argv++; --argc;
-        if (strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) {
-            if (argc < 1) {
-                ReportErrorMessage2("%s requires class path specification",
-                                    arg, JNI_TRUE);
-                PrintUsage();
-                return JNI_FALSE;
-            }
-            SetClassPath(*argv);
-            argv++; --argc;
-        } else if (strcmp(arg, "-jar") == 0) {
-            jarflag = JNI_TRUE;
-        } else if (strcmp(arg, "-help") == 0 ||
-                   strcmp(arg, "-h") == 0 ||
-                   strcmp(arg, "-?") == 0) {
-            PrintUsage();
-            *pret = 0;
-            return JNI_FALSE;
-        } else if (strcmp(arg, "-version") == 0) {
-            printVersion = JNI_TRUE;
-            return JNI_TRUE;
-        } else if (strcmp(arg, "-showversion") == 0) {
-            showVersion = JNI_TRUE;
-        } else if (strcmp(arg, "-X") == 0) {
-            *pret = PrintXUsage();
-            return JNI_FALSE;
-/*
- * The following case provide backward compatibility with old-style
- * command line options.
- */
-        } else if (strcmp(arg, "-fullversion") == 0) {
-            fprintf(stderr, "%s full version \"%s\"\n", progname,
-                    FULL_VERSION);
-            *pret = 0;
-            return JNI_FALSE;
-        } else if (strcmp(arg, "-verbosegc") == 0) {
-            AddOption("-verbose:gc", NULL);
-        } else if (strcmp(arg, "-t") == 0) {
-            AddOption("-Xt", NULL);
-        } else if (strcmp(arg, "-tm") == 0) {
-            AddOption("-Xtm", NULL);
-        } else if (strcmp(arg, "-debug") == 0) {
-            AddOption("-Xdebug", NULL);
-        } else if (strcmp(arg, "-noclassgc") == 0) {
-            AddOption("-Xnoclassgc", NULL);
-        } else if (strcmp(arg, "-Xfuture") == 0) {
-            AddOption("-Xverify:all", NULL);
-        } else if (strcmp(arg, "-verify") == 0) {
-            AddOption("-Xverify:all", NULL);
-        } else if (strcmp(arg, "-verifyremote") == 0) {
-            AddOption("-Xverify:remote", NULL);
-        } else if (strcmp(arg, "-noverify") == 0) {
-            AddOption("-Xverify:none", NULL);
-        } else if (strcmp(arg, "-XXsuppressExitMessage") == 0) {
-            noExitErrorMessage = 1;
-        } else if (strncmp(arg, "-prof", 5) == 0) {
-            char *p = arg + 5;
-            char *tmp = MemAlloc(strlen(arg) + 50);
-            if (*p) {
-                sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1);
-            } else {
-                sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof");
-            }
-            AddOption(tmp, NULL);
-        } else if (strncmp(arg, "-ss", 3) == 0 ||
-                   strncmp(arg, "-oss", 4) == 0 ||
-                   strncmp(arg, "-ms", 3) == 0 ||
-                   strncmp(arg, "-mx", 3) == 0) {
-            char *tmp = MemAlloc(strlen(arg) + 6);
-            sprintf(tmp, "-X%s", arg + 1); /* skip '-' */
-            AddOption(tmp, NULL);
-        } else if (strcmp(arg, "-checksource") == 0 ||
-                   strcmp(arg, "-cs") == 0 ||
-                   strcmp(arg, "-noasyncgc") == 0) {
-            /* No longer supported */
-            fprintf(stderr,
-                    "Warning: %s option is no longer supported.\n",
-                    arg);
-        } else if (strncmp(arg, "-version:", 9) == 0 ||
-                   strcmp(arg, "-no-jre-restrict-search") == 0 ||
-                   strcmp(arg, "-jre-restrict-search") == 0) {
-            ; /* Ignore machine independent options already handled */
-        } else if (RemovableMachineDependentOption(arg) ) {
-            ; /* Do not pass option to vm. */
-        }
-        else {
-            AddOption(arg, NULL);
-        }
-    }
-
-    if (--argc >= 0) {
-        if (jarflag) {
-            *pjarfile = *argv++;
-            *pclassname = 0;
-        } else {
-            *pjarfile = 0;
-            *pclassname = *argv++;
-        }
-        *pargc = argc;
-        *pargv = argv;
-    }
-
-    return JNI_TRUE;
-}
-
-/*
- * Initializes the Java Virtual Machine. Also frees options array when
- * finished.
- */
-static jboolean
-InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn)
-{
-    JavaVMInitArgs args;
-    jint r;
-
-    memset(&args, 0, sizeof(args));
-    args.version  = JNI_VERSION_1_2;
-    args.nOptions = numOptions;
-    args.options  = options;
-    args.ignoreUnrecognized = JNI_FALSE;
-
-    if (_launcher_debug) {
-        int i = 0;
-        printf("JavaVM args:\n    ");
-        printf("version 0x%08lx, ", (long)args.version);
-        printf("ignoreUnrecognized is %s, ",
-               args.ignoreUnrecognized ? "JNI_TRUE" : "JNI_FALSE");
-        printf("nOptions is %ld\n", (long)args.nOptions);
-        for (i = 0; i < numOptions; i++)
-            printf("    option[%2d] = '%s'\n",
-                   i, args.options[i].optionString);
-    }
-
-    r = ifn->CreateJavaVM(pvm, (void **)penv, &args);
-    free(options);
-    return r == JNI_OK;
-}
-
-
-#define NULL_CHECK0(e) if ((e) == 0) return 0
-#define NULL_CHECK(e) if ((e) == 0) return
-
-/*
- * Returns a pointer to a block of at least 'size' bytes of memory.
- * Prints error message and exits if the memory could not be allocated.
- */
-void *
-MemAlloc(size_t size)
-{
-    void *p = malloc(size);
-    if (p == 0) {
-        perror("malloc");
-        exit(1);
-    }
-    return p;
-}
-
-static jstring platformEncoding = NULL;
-static jstring getPlatformEncoding(JNIEnv *env) {
-    if (platformEncoding == NULL) {
-        jstring propname = (*env)->NewStringUTF(env, "sun.jnu.encoding");
-        if (propname) {
-            jclass cls;
-            jmethodID mid;
-            NULL_CHECK0 (cls = FindBootStrapClass(env, "java/lang/System"));
-            NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
-                                   env, cls,
-                                   "getProperty",
-                                   "(Ljava/lang/String;)Ljava/lang/String;"));
-            platformEncoding = (*env)->CallStaticObjectMethod (
-                                    env, cls, mid, propname);
-        }
-    }
-    return platformEncoding;
-}
-
-static jboolean isEncodingSupported(JNIEnv *env, jstring enc) {
-    jclass cls;
-    jmethodID mid;
-    NULL_CHECK0 (cls = FindBootStrapClass(env, "java/nio/charset/Charset"));
-    NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
-                           env, cls,
-                           "isSupported",
-                           "(Ljava/lang/String;)Z"));
-    return (jboolean)(*env)->CallStaticObjectMethod (env, cls, mid, enc);
-}
-
-/*
- * Returns a new Java string object for the specified platform string.
- */
-static jstring
-NewPlatformString(JNIEnv *env, char *s)
-{
-    int len = (int)strlen(s);
-    jclass cls;
-    jmethodID mid;
-    jbyteArray ary;
-    jstring enc;
-
-    if (s == NULL)
-        return 0;
-    enc = getPlatformEncoding(env);
-
-    ary = (*env)->NewByteArray(env, len);
-    if (ary != 0) {
-        jstring str = 0;
-        (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s);
-        if (!(*env)->ExceptionOccurred(env)) {
-#ifdef GAMMA
-            /* We support running JVM with older JDK, so here we have to deal */
-            /* with the case that sun.jnu.encoding is undefined (enc == NULL) */
-            if (enc != NULL && isEncodingSupported(env, enc) == JNI_TRUE) {
-#else
-            if (isEncodingSupported(env, enc) == JNI_TRUE) {
-#endif
-                NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
-                NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
-                                          "([BLjava/lang/String;)V"));
-                str = (*env)->NewObject(env, cls, mid, ary, enc);
-            } else {
-                /*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.
-                */
-                NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
-                NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
-                                          "([B)V"));
-                str = (*env)->NewObject(env, cls, mid, ary);
-            }
-            (*env)->DeleteLocalRef(env, ary);
-            return str;
-        }
-    }
-    return 0;
-}
-
-/*
- * Returns a new array of Java string objects for the specified
- * array of platform strings.
- */
-static jobjectArray
-NewPlatformStringArray(JNIEnv *env, char **strv, int strc)
-{
-    jarray cls;
-    jarray ary;
-    int i;
-
-    NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
-    NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0));
-    for (i = 0; i < strc; i++) {
-        jstring str = NewPlatformString(env, *strv++);
-        NULL_CHECK0(str);
-        (*env)->SetObjectArrayElement(env, ary, i, str);
-        (*env)->DeleteLocalRef(env, str);
-    }
-    return ary;
-}
-
-/*
- * Loads a class, convert the '.' to '/'.
- */
-static jclass
-LoadClass(JNIEnv *env, char *name)
-{
-    char *buf = MemAlloc(strlen(name) + 1);
-    char *s = buf, *t = name, c;
-    jclass cls;
-    jlong start, end;
-
-    if (_launcher_debug)
-        start = CounterGet();
-
-    do {
-        c = *t++;
-        *s++ = (c == '.') ? '/' : c;
-    } while (c != '\0');
-    // use the application class loader for the main-class
-    cls = (*env)->FindClass(env, buf);
-    free(buf);
-
-    if (_launcher_debug) {
-        end   = CounterGet();
-        printf("%ld micro seconds to load main class\n",
-               (long)(jint)Counter2Micros(end-start));
-        printf("----_JAVA_LAUNCHER_DEBUG----\n");
-    }
-
-    return cls;
-}
-
-
-/*
- * Returns the main class name for the specified jar file.
- */
-static jstring
-GetMainClassName(JNIEnv *env, char *jarname)
-{
-#define MAIN_CLASS "Main-Class"
-    jclass cls;
-    jmethodID mid;
-    jobject jar, man, attr;
-    jstring str, result = 0;
-
-    NULL_CHECK0(cls = FindBootStrapClass(env, "java/util/jar/JarFile"));
-    NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
-                                          "(Ljava/lang/String;)V"));
-    NULL_CHECK0(str = NewPlatformString(env, jarname));
-    NULL_CHECK0(jar = (*env)->NewObject(env, cls, mid, str));
-    NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "getManifest",
-                                          "()Ljava/util/jar/Manifest;"));
-    man = (*env)->CallObjectMethod(env, jar, mid);
-    if (man != 0) {
-        NULL_CHECK0(mid = (*env)->GetMethodID(env,
-                                    (*env)->GetObjectClass(env, man),
-                                    "getMainAttributes",
-                                    "()Ljava/util/jar/Attributes;"));
-        attr = (*env)->CallObjectMethod(env, man, mid);
-        if (attr != 0) {
-            NULL_CHECK0(mid = (*env)->GetMethodID(env,
-                                    (*env)->GetObjectClass(env, attr),
-                                    "getValue",
-                                    "(Ljava/lang/String;)Ljava/lang/String;"));
-            NULL_CHECK0(str = NewPlatformString(env, MAIN_CLASS));
-            result = (*env)->CallObjectMethod(env, attr, mid, str);
-        }
-    }
-    return result;
-}
-
-#ifdef JAVA_ARGS
-static char *java_args[] = JAVA_ARGS;
-static char *app_classpath[] = APP_CLASSPATH;
-
-/*
- * For tools convert 'javac -J-ms32m' to 'java -ms32m ...'
- */
-static void
-TranslateDashJArgs(int *pargc, char ***pargv)
-{
-    const int NUM_ARGS = (sizeof(java_args) / sizeof(char *));
-    int argc = *pargc;
-    char **argv = *pargv;
-    int nargc = argc + NUM_ARGS;
-    char **nargv = MemAlloc((nargc + 1) * sizeof(char *));
-    int i;
-
-    *pargc = nargc;
-    *pargv = nargv;
-
-    /* Copy the VM arguments (i.e. prefixed with -J) */
-    for (i = 0; i < NUM_ARGS; i++) {
-        char *arg = java_args[i];
-        if (arg[0] == '-' && arg[1] == 'J') {
-            *nargv++ = arg + 2;
-        }
-    }
-
-    for (i = 0; i < argc; i++) {
-        char *arg = argv[i];
-        if (arg[0] == '-' && arg[1] == 'J') {
-            if (arg[2] == '\0') {
-                ReportErrorMessage("Error: the -J option should not be "
-                                   "followed by a space.", JNI_TRUE);
-                exit(1);
-            }
-            *nargv++ = arg + 2;
-        }
-    }
-
-    /* Copy the rest of the arguments */
-    for (i = 0; i < NUM_ARGS; i++) {
-        char *arg = java_args[i];
-        if (arg[0] != '-' || arg[1] != 'J') {
-            *nargv++ = arg;
-        }
-    }
-    for (i = 0; i < argc; i++) {
-        char *arg = argv[i];
-        if (arg[0] != '-' || arg[1] != 'J') {
-            *nargv++ = arg;
-        }
-    }
-    *nargv = 0;
-}
-
-/*
- * For our tools, we try to add 3 VM options:
- *      -Denv.class.path=<envcp>
- *      -Dapplication.home=<apphome>
- *      -Djava.class.path=<appcp>
- * <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 classes (sun.tools.javac.Main) only if they explicitly add
- *           tools.jar to CLASSPATH.
- * <apphome> is the directory where the application is installed.
- * <appcp>   is the classpath to where our apps' classfiles are.
- */
-static jboolean
-AddApplicationOptions()
-{
-    const int NUM_APP_CLASSPATH = (sizeof(app_classpath) / sizeof(char *));
-    char *s, *envcp, *appcp, *apphome;
-    char home[MAXPATHLEN]; /* application home */
-    char separator[] = { PATH_SEPARATOR, '\0' };
-    int size, i;
-    int strlenHome;
-
-    s = getenv("CLASSPATH");
-    if (s) {
-        /* 40 for -Denv.class.path= */
-        envcp = (char *)MemAlloc(strlen(s) + 40);
-        sprintf(envcp, "-Denv.class.path=%s", s);
-        AddOption(envcp, NULL);
-    }
-
-    if (!GetApplicationHome(home, sizeof(home))) {
-        ReportErrorMessage("Can't determine application home", JNI_TRUE);
-        return JNI_FALSE;
-    }
-
-    /* 40 for '-Dapplication.home=' */
-    apphome = (char *)MemAlloc(strlen(home) + 40);
-    sprintf(apphome, "-Dapplication.home=%s", home);
-    AddOption(apphome, NULL);
-
-    /* How big is the application's classpath? */
-    size = 40;                                 /* 40: "-Djava.class.path=" */
-    strlenHome = (int)strlen(home);
-    for (i = 0; i < NUM_APP_CLASSPATH; i++) {
-        size += strlenHome + (int)strlen(app_classpath[i]) + 1; /* 1: separator */
-    }
-    appcp = (char *)MemAlloc(size + 1);
-    strcpy(appcp, "-Djava.class.path=");
-    for (i = 0; i < NUM_APP_CLASSPATH; i++) {
-        strcat(appcp, home);                    /* c:\program files\myapp */
-        strcat(appcp, app_classpath[i]);        /* \lib\myapp.jar         */
-        strcat(appcp, separator);               /* ;                      */
-    }
-    appcp[strlen(appcp)-1] = '\0';  /* remove trailing path separator */
-    AddOption(appcp, NULL);
-    return JNI_TRUE;
-}
-#endif
-
-/*
- * 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.
- */
-void
-SetJavaCommandLineProp(char *classname, char *jarfile,
-                       int argc, char **argv)
-{
-
-    int i = 0;
-    size_t len = 0;
-    char* javaCommand = NULL;
-    char* dashDstr = "-Dsun.java.command=";
-
-    if (classname == NULL && jarfile == NULL) {
-        /* unexpected, one of these should be set. just return without
-         * setting the property
-         */
-        return;
-    }
-
-    /* if the class name is not set, then use the jarfile name */
-    if (classname == NULL) {
-        classname = jarfile;
-    }
-
-    /* determine the amount of memory to allocate assuming
-     * the individual components will be space separated
-     */
-    len = strlen(classname);
-    for (i = 0; i < argc; i++) {
-        len += strlen(argv[i]) + 1;
-    }
-
-    /* allocate the memory */
-    javaCommand = (char*) MemAlloc(len + strlen(dashDstr) + 1);
-
-    /* build the -D string */
-    *javaCommand = '\0';
-    strcat(javaCommand, dashDstr);
-    strcat(javaCommand, classname);
-
-    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.
-         */
-        strcat(javaCommand, " ");
-        strcat(javaCommand, argv[i]);
-    }
-
-    AddOption(javaCommand, NULL);
-}
-
-/*
- * JVM wants to know launcher type, so tell it.
- */
-#ifdef GAMMA
-void SetJavaLauncherProp() {
-  AddOption("-Dsun.java.launcher=" LAUNCHER_TYPE, NULL);
-}
-#endif
-
-/*
- * Prints the version information from the java.version and other properties.
- */
-static void
-PrintJavaVersion(JNIEnv *env)
-{
-    jclass ver;
-    jmethodID print;
-
-    NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version"));
-    NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, "print", "()V"));
-
-    (*env)->CallStaticVoidMethod(env, ver, print);
-}
-
-/*
- * Prints default usage message.
- */
-static void
-PrintUsage(void)
-{
-    int i;
-
-    fprintf(stdout,
-        "Usage: %s [-options] class [args...]\n"
-        "           (to execute a class)\n"
-        "   or  %s [-options] -jar jarfile [args...]\n"
-        "           (to execute a jar file)\n"
-        "\n"
-        "where options include:\n",
-        progname,
-        progname);
-
-#ifndef GAMMA
-    PrintMachineDependentOptions();
-
-    if ((knownVMs[0].flag == VM_KNOWN) ||
-        (knownVMs[0].flag == VM_IF_SERVER_CLASS)) {
-      fprintf(stdout, "    %s\t  to select the \"%s\" VM\n",
-              knownVMs[0].name, knownVMs[0].name+1);
-    }
-    for (i=1; i<knownVMsCount; i++) {
-        if (knownVMs[i].flag == VM_KNOWN)
-            fprintf(stdout, "    %s\t  to select the \"%s\" VM\n",
-                    knownVMs[i].name, knownVMs[i].name+1);
-    }
-    for (i=1; i<knownVMsCount; i++) {
-        if (knownVMs[i].flag == VM_ALIASED_TO)
-            fprintf(stdout, "    %s\t  is a synonym for "
-                    "the \"%s\" VM  [deprecated]\n",
-                    knownVMs[i].name, knownVMs[i].alias+1);
-    }
-
-    /* The first known VM is the default */
-    {
-      const char* defaultVM   = knownVMs[0].name+1;
-      const char* punctuation = ".";
-      const char* reason      = "";
-      if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) &&
-          (ServerClassMachine() == JNI_TRUE)) {
-        defaultVM = knownVMs[0].server_class+1;
-        punctuation = ", ";
-        reason = "because you are running on a server-class machine.\n";
-      }
-      fprintf(stdout, "                  The default VM is %s%s\n",
-              defaultVM, punctuation);
-      fprintf(stdout, "                  %s\n",
-              reason);
-    }
-#endif /* ifndef GAMMA */
-
-    fprintf(stdout,
-"    -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"
-"    -D<name>=<value>\n"
-"                  set a system property\n"
-"    -verbose[:class|gc|jni]\n"
-"                  enable verbose output\n"
-"    -version      print product version and exit\n"
-"    -version:<value>\n"
-"                  require the specified version to run\n"
-"    -showversion  print product version and continue\n"
-"    -jre-restrict-search | -jre-no-restrict-search\n"
-"                  include/exclude user private JREs in the version search\n"
-"    -? -help      print this help message\n"
-"    -X            print help on non-standard options\n"
-"    -ea[:<packagename>...|:<classname>]\n"
-"    -enableassertions[:<packagename>...|:<classname>]\n"
-"                  enable assertions\n"
-"    -da[:<packagename>...|:<classname>]\n"
-"    -disableassertions[:<packagename>...|:<classname>]\n"
-"                  disable assertions\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"
-
-            ,PATH_SEPARATOR);
-}
-
-/*
- * Print usage message for -X options.
- */
-static jint
-PrintXUsage(void)
-{
-    char path[MAXPATHLEN];
-    char buf[128];
-    size_t n;
-    FILE *fp;
-
-    GetXUsagePath(path, sizeof(path));
-    fp = fopen(path, "r");
-    if (fp == 0) {
-        fprintf(stderr, "Can't open %s\n", path);
-        return 1;
-    }
-    while ((n = fread(buf, 1, sizeof(buf), fp)) != 0) {
-        fwrite(buf, 1, n, stdout);
-    }
-    fclose(fp);
-    return 0;
-}
-
-#ifndef GAMMA
-
-/*
- * 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:
- *
- *     jvmcfg         :=  { vmLine }
- *     vmLine         :=  knownLine
- *                    |   aliasLine
- *                    |   warnLine
- *                    |   ignoreLine
- *                    |   errorLine
- *                    |   predicateLine
- *                    |   commentLine
- *     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
- *     flag           :=  "-" identifier
- *
- * 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
- * mechanism.
- */
-jint
-ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative)
-{
-    FILE *jvmCfg;
-    char jvmCfgName[MAXPATHLEN+20];
-    char line[MAXPATHLEN+20];
-    int cnt = 0;
-    int lineno = 0;
-    jlong start, end;
-    int vmType;
-    char *tmpPtr;
-    char *altVMName;
-    char *serverClassVMName;
-    static char *whiteSpace = " \t";
-    if (_launcher_debug) {
-        start = CounterGet();
-    }
-
-    strcpy(jvmCfgName, jrepath);
-    strcat(jvmCfgName, FILESEP "lib" FILESEP);
-    strcat(jvmCfgName, arch);
-    strcat(jvmCfgName, FILESEP "jvm.cfg");
-
-    jvmCfg = fopen(jvmCfgName, "r");
-    if (jvmCfg == NULL) {
-      if (!speculative) {
-        ReportErrorMessage2("Error: could not open `%s'", jvmCfgName,
-                            JNI_TRUE);
-        exit(1);
-      } else {
-        return -1;
-      }
-    }
-    while (fgets(line, sizeof(line), jvmCfg) != NULL) {
-        vmType = VM_UNKNOWN;
-        lineno++;
-        if (line[0] == '#')
-            continue;
-        if (line[0] != '-') {
-            fprintf(stderr, "Warning: no leading - on line %d of `%s'\n",
-                    lineno, jvmCfgName);
-        }
-        if (cnt >= knownVMsLimit) {
-            GrowKnownVMs(cnt);
-        }
-        line[strlen(line)-1] = '\0'; /* remove trailing newline */
-        tmpPtr = line + strcspn(line, whiteSpace);
-        if (*tmpPtr == 0) {
-            fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n",
-                    lineno, jvmCfgName);
-        } else {
-            /* Null-terminate this string for strdup below */
-            *tmpPtr++ = 0;
-            tmpPtr += strspn(tmpPtr, whiteSpace);
-            if (*tmpPtr == 0) {
-                fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n",
-                        lineno, jvmCfgName);
-            } else {
-                if (!strncmp(tmpPtr, "KNOWN", strlen("KNOWN"))) {
-                    vmType = VM_KNOWN;
-                } else if (!strncmp(tmpPtr, "ALIASED_TO", strlen("ALIASED_TO"))) {
-                    tmpPtr += strcspn(tmpPtr, whiteSpace);
-                    if (*tmpPtr != 0) {
-                        tmpPtr += strspn(tmpPtr, whiteSpace);
-                    }
-                    if (*tmpPtr == 0) {
-                        fprintf(stderr, "Warning: missing VM alias on line %d of `%s'\n",
-                                lineno, jvmCfgName);
-                    } else {
-                        /* Null terminate altVMName */
-                        altVMName = tmpPtr;
-                        tmpPtr += strcspn(tmpPtr, whiteSpace);
-                        *tmpPtr = 0;
-                        vmType = VM_ALIASED_TO;
-                    }
-                } else if (!strncmp(tmpPtr, "WARN", strlen("WARN"))) {
-                    vmType = VM_WARN;
-                } else if (!strncmp(tmpPtr, "IGNORE", strlen("IGNORE"))) {
-                    vmType = VM_IGNORE;
-                } else if (!strncmp(tmpPtr, "ERROR", strlen("ERROR"))) {
-                    vmType = VM_ERROR;
-                } else if (!strncmp(tmpPtr,
-                                    "IF_SERVER_CLASS",
-                                    strlen("IF_SERVER_CLASS"))) {
-                    tmpPtr += strcspn(tmpPtr, whiteSpace);
-                    if (*tmpPtr != 0) {
-                        tmpPtr += strspn(tmpPtr, whiteSpace);
-                    }
-                    if (*tmpPtr == 0) {
-                        fprintf(stderr, "Warning: missing server class VM on line %d of `%s'\n",
-                                lineno, jvmCfgName);
-                    } else {
-                        /* Null terminate server class VM name */
-                        serverClassVMName = tmpPtr;
-                        tmpPtr += strcspn(tmpPtr, whiteSpace);
-                        *tmpPtr = 0;
-                        vmType = VM_IF_SERVER_CLASS;
-                    }
-                } else {
-                    fprintf(stderr, "Warning: unknown VM type on line %d of `%s'\n",
-                            lineno, &jvmCfgName[0]);
-                    vmType = VM_KNOWN;
-                }
-            }
-        }
-
-        if (_launcher_debug)
-            printf("jvm.cfg[%d] = ->%s<-\n", cnt, line);
-        if (vmType != VM_UNKNOWN) {
-            knownVMs[cnt].name = strdup(line);
-            knownVMs[cnt].flag = vmType;
-            switch (vmType) {
-            default:
-                break;
-            case VM_ALIASED_TO:
-                knownVMs[cnt].alias = strdup(altVMName);
-                if (_launcher_debug) {
-                    printf("    name: %s  vmType: %s  alias: %s\n",
-                           knownVMs[cnt].name, "VM_ALIASED_TO", knownVMs[cnt].alias);
-                }
-                break;
-            case VM_IF_SERVER_CLASS:
-                knownVMs[cnt].server_class = strdup(serverClassVMName);
-                if (_launcher_debug) {
-                    printf("    name: %s  vmType: %s  server_class: %s\n",
-                           knownVMs[cnt].name, "VM_IF_SERVER_CLASS", knownVMs[cnt].server_class);
-                }
-                break;
-            }
-            cnt++;
-        }
-    }
-    fclose(jvmCfg);
-    knownVMsCount = cnt;
-
-    if (_launcher_debug) {
-        end   = CounterGet();
-        printf("%ld micro seconds to parse jvm.cfg\n",
-               (long)(jint)Counter2Micros(end-start));
-    }
-
-    return cnt;
-}
-
-
-static void
-GrowKnownVMs(int minimum)
-{
-    struct vmdesc* newKnownVMs;
-    int newMax;
-
-    newMax = (knownVMsLimit == 0 ? INIT_MAX_KNOWN_VMS : (2 * knownVMsLimit));
-    if (newMax <= minimum) {
-        newMax = minimum;
-    }
-    newKnownVMs = (struct vmdesc*) MemAlloc(newMax * sizeof(struct vmdesc));
-    if (knownVMs != NULL) {
-        memcpy(newKnownVMs, knownVMs, knownVMsLimit * sizeof(struct vmdesc));
-    }
-    free(knownVMs);
-    knownVMs = newKnownVMs;
-    knownVMsLimit = newMax;
-}
-
-
-/* Returns index of VM or -1 if not found */
-static int
-KnownVMIndex(const char* name)
-{
-    int i;
-    if (strncmp(name, "-J", 2) == 0) name += 2;
-    for (i = 0; i < knownVMsCount; i++) {
-        if (!strcmp(name, knownVMs[i].name)) {
-            return i;
-        }
-    }
-    return -1;
-}
-
-static void
-FreeKnownVMs()
-{
-    int i;
-    for (i = 0; i < knownVMsCount; i++) {
-        free(knownVMs[i].name);
-        knownVMs[i].name = NULL;
-    }
-    free(knownVMs);
-}
-
-#endif /* ifndef GAMMA */
--- a/hotspot/src/os/solaris/launcher/java.h	Thu Dec 02 20:01:47 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK,
- * search "GAMMA" for gamma specific changes.
- */
-
-#ifndef _JAVA_H_
-#define _JAVA_H_
-
-/*
- * Get system specific defines.
- */
-#include "jni.h"
-#include "java_md.h"
-
-/*
- * Pointers to the needed JNI invocation API, initialized by LoadJavaVM.
- */
-typedef jint (JNICALL *CreateJavaVM_t)(JavaVM **pvm, void **env, void *args);
-typedef jint (JNICALL *GetDefaultJavaVMInitArgs_t)(void *args);
-
-typedef struct {
-    CreateJavaVM_t CreateJavaVM;
-    GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs;
-} InvocationFunctions;
-
-/*
- * Prototypes for launcher functions in the system specific java_md.c.
- */
-
-jboolean
-LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn);
-
-void
-GetXUsagePath(char *buf, jint bufsize);
-
-jboolean
-GetApplicationHome(char *buf, jint bufsize);
-
-const char *
-GetArch();
-
-void CreateExecutionEnvironment(int *_argc,
-                                       char ***_argv,
-                                       char jrepath[],
-                                       jint so_jrepath,
-                                       char jvmpath[],
-                                       jint so_jvmpath,
-                                       char **original_argv);
-
-/*
- * Report an error message to stderr or a window as appropriate.  The
- * flag always is set to JNI_TRUE if message is to be reported to both
- * strerr and windows and set to JNI_FALSE if the message should only
- * be sent to a window.
- */
-void ReportErrorMessage(char * message, jboolean always);
-void ReportErrorMessage2(char * format, char * string, jboolean always);
-
-/*
- * Report an exception which terminates the vm to stderr or a window
- * as appropriate.
- */
-void ReportExceptionDescription(JNIEnv * env);
-
-jboolean RemovableMachineDependentOption(char * option);
-void PrintMachineDependentOptions();
-
-/*
- * Functions defined in java.c and used in java_md.c.
- */
-jint ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative);
-char *CheckJvmType(int *argc, char ***argv, jboolean speculative);
-void* MemAlloc(size_t size);
-
-/*
- * Make launcher spit debug output.
- */
-extern jboolean _launcher_debug;
-
-/*
- * This allows for finding classes from the VM's bootstrap class loader
- * directly, FindClass uses the application class loader internally, this will
- * cause unnecessary searching of the classpath for the required classes.
- */
-typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env,
-                                                const char *name,
-                                                jboolean throwError));
-
-jclass FindBootStrapClass(JNIEnv *env, const char *classname);
-
-#endif /* _JAVA_H_ */
--- a/hotspot/src/os/solaris/launcher/java_md.c	Thu Dec 02 20:01:47 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1849 +0,0 @@
-/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK,
- * search "GAMMA" for gamma specific changes.
- */
-
-#include "java.h"
-#include <dirent.h>
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/types.h>
-
-#ifndef GAMMA
-#include "manifest_info.h"
-#include "version_comp.h"
-#endif
-
-#define JVM_DLL "libjvm.so"
-#define JAVA_DLL "libjava.so"
-
-#ifndef GAMMA   /* launcher.make defines ARCH */
-
-/*
- * If a processor / os combination has the ability to run binaries of
- * two data models and cohabitation of jre/jdk bits with both data
- * models is supported, then DUAL_MODE is defined.  When DUAL_MODE is
- * defined, the architecture names for the narrow and wide version of
- * the architecture are defined in BIG_ARCH and SMALL_ARCH.  Currently
- * only Solaris on sparc/sparcv9 and i586/amd64 is DUAL_MODE; linux
- * i586/amd64 could be defined as DUAL_MODE but that is not the
- * current policy.
- */
-
-#ifdef _LP64
-
-#  ifdef ia64
-#    define ARCH "ia64"
-#  elif defined(amd64)
-#    define ARCH "amd64"
-#  elif defined(__sparc)
-#    define ARCH "sparcv9"
-#  else
-#    define ARCH "unknown" /* unknown 64-bit architecture */
-#  endif
-
-#else /* 32-bit data model */
-
-#  ifdef i586
-#    define ARCH "i386"
-#  elif defined(__sparc)
-#    define ARCH "sparc"
-#  endif
-
-#endif /* _LP64 */
-
-#ifdef __sun
-#  define DUAL_MODE
-#  ifdef __sparc
-#    define BIG_ARCH "sparcv9"
-#    define SMALL_ARCH "sparc"
-#  else
-#    define BIG_ARCH "amd64"
-#    define SMALL_ARCH "i386"
-#  endif
-#  include <sys/systeminfo.h>
-#  include <sys/elf.h>
-#  include <stdio.h>
-#else
-#  ifndef ARCH
-#    include <sys/systeminfo.h>
-#  endif
-#endif
-
-#endif /* ifndef GAMMA */
-
-/* pointer to environment */
-extern char **environ;
-
-#ifndef GAMMA
-
-/*
- *      A collection of useful strings. One should think of these as #define
- *      entries, but actual strings can be more efficient (with many compilers).
- */
-#ifdef __linux__
-static const char *system_dir   = "/usr/java";
-static const char *user_dir     = "/java";
-#else /* Solaris */
-static const char *system_dir   = "/usr/jdk";
-static const char *user_dir     = "/jdk";
-#endif
-
-#endif  /* ifndef GAMMA */
-
-/*
- * Flowchart of launcher execs and options processing on unix
- *
- * The selection of the proper vm shared library to open depends on
- * several classes of command line options, including vm "flavor"
- * options (-client, -server) and the data model options, -d32  and
- * -d64, as well as a version specification which may have come from
- * the command line or from the manifest of an executable jar file.
- * The vm selection options are not passed to the running
- * virtual machine; they must be screened out by the launcher.
- *
- * The version specification (if any) is processed first by the
- * platform independent routine SelectVersion.  This may result in
- * the exec of the specified launcher version.
- *
- * Typically, the launcher execs at least once to ensure a suitable
- * LD_LIBRARY_PATH is in effect for the process.  The first exec
- * screens out all the data model options; leaving the choice of data
- * model implicit in the binary selected to run.  However, in case no
- * exec is done, the data model options are screened out before the vm
- * is invoked.
- *
- *  incoming argv ------------------------------
- *  |                                          |
- * \|/                                         |
- * CheckJVMType                                |
- * (removes -client, -server, etc.)            |
- *                                            \|/
- *                                            CreateExecutionEnvironment
- *                                            (removes -d32 and -d64,
- *                                             determines desired data model,
- *                                             sets up LD_LIBRARY_PATH,
- *                                             and exec's)
- *                                             |
- *  --------------------------------------------
- *  |
- * \|/
- * exec child 1 incoming argv -----------------
- *  |                                          |
- * \|/                                         |
- * CheckJVMType                                |
- * (removes -client, -server, etc.)            |
- *  |                                         \|/
- *  |                                          CreateExecutionEnvironment
- *  |                                          (verifies desired data model
- *  |                                           is running and acceptable
- *  |                                           LD_LIBRARY_PATH;
- *  |                                           no-op in child)
- *  |
- * \|/
- * TranslateDashJArgs...
- * (Prepare to pass args to vm)
- *  |
- *  |
- *  |
- * \|/
- * ParseArguments
- * (ignores -d32 and -d64,
- *  processes version options,
- *  creates argument list for vm,
- *  etc.)
- *
- */
-
-static char *SetExecname(char **argv);
-static char * GetExecname();
-static jboolean GetJVMPath(const char *jrepath, const char *jvmtype,
-                           char *jvmpath, jint jvmpathsize, char * arch);
-static jboolean GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative);
-
-const char *
-GetArch()
-{
-    static char *arch = NULL;
-    static char buf[12];
-    if (arch) {
-        return arch;
-    }
-
-#ifdef ARCH
-    strcpy(buf, ARCH);
-#else
-    sysinfo(SI_ARCHITECTURE, buf, sizeof(buf));
-#endif
-    arch = buf;
-    return arch;
-}
-
-void
-CreateExecutionEnvironment(int *_argcp,
-                           char ***_argvp,
-                           char jrepath[],
-                           jint so_jrepath,
-                           char jvmpath[],
-                           jint so_jvmpath,
-                           char **original_argv) {
-  /*
-   * First, determine if we are running the desired data model.  If we
-   * are running the desired data model, all the error messages
-   * associated with calling GetJREPath, ReadKnownVMs, etc. should be
-   * output.  However, if we are not running the desired data model,
-   * some of the errors should be suppressed since it is more
-   * informative to issue an error message based on whether or not the
-   * os/processor combination has dual mode capabilities.
-   */
-
-    char *execname = NULL;
-    int original_argc = *_argcp;
-    jboolean jvmpathExists;
-
-    /* Compute the name of the executable */
-    execname = SetExecname(*_argvp);
-
-#ifndef GAMMA
-    /* Set the LD_LIBRARY_PATH environment variable, check data model
-       flags, and exec process, if needed */
-    {
-      char *arch        = (char *)GetArch(); /* like sparc or sparcv9 */
-      char * jvmtype    = NULL;
-      int argc          = *_argcp;
-      char **argv       = original_argv;
-
-      char *runpath     = NULL; /* existing effective LD_LIBRARY_PATH
-                                   setting */
-
-      int running       =       /* What data model is being ILP32 =>
-                                   32 bit vm; LP64 => 64 bit vm */
-#ifdef _LP64
-        64;
-#else
-      32;
-#endif
-
-      int wanted        = running;      /* What data mode is being
-                                           asked for? Current model is
-                                           fine unless another model
-                                           is asked for */
-
-      char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */
-      char* newpath     = NULL; /* path on new LD_LIBRARY_PATH */
-      char* lastslash   = NULL;
-
-      char** newenvp    = NULL; /* current environment */
-
-      char** newargv    = NULL;
-      int    newargc    = 0;
-#ifdef __sun
-      char*  dmpath     = NULL;  /* data model specific LD_LIBRARY_PATH,
-                                    Solaris only */
-#endif
-
-      /*
-       * Starting in 1.5, all unix platforms accept the -d32 and -d64
-       * options.  On platforms where only one data-model is supported
-       * (e.g. ia-64 Linux), using the flag for the other data model is
-       * an error and will terminate the program.
-       */
-
-      { /* open new scope to declare local variables */
-        int i;
-
-        newargv = (char **)MemAlloc((argc+1) * sizeof(*newargv));
-        newargv[newargc++] = argv[0];
-
-        /* scan for data model arguments and remove from argument list;
-           last occurrence determines desired data model */
-        for (i=1; i < argc; i++) {
-
-          if (strcmp(argv[i], "-J-d64") == 0 || strcmp(argv[i], "-d64") == 0) {
-            wanted = 64;
-            continue;
-          }
-          if (strcmp(argv[i], "-J-d32") == 0 || strcmp(argv[i], "-d32") == 0) {
-            wanted = 32;
-            continue;
-          }
-          newargv[newargc++] = argv[i];
-
-#ifdef JAVA_ARGS
-          if (argv[i][0] != '-')
-            continue;
-#else
-          if (strcmp(argv[i], "-classpath") == 0 || strcmp(argv[i], "-cp") == 0) {
-            i++;
-            if (i >= argc) break;
-            newargv[newargc++] = argv[i];
-            continue;
-          }
-          if (argv[i][0] != '-') { i++; break; }
-#endif
-        }
-
-        /* copy rest of args [i .. argc) */
-        while (i < argc) {
-          newargv[newargc++] = argv[i++];
-        }
-        newargv[newargc] = NULL;
-
-        /*
-         * newargv has all proper arguments here
-         */
-
-        argc = newargc;
-        argv = newargv;
-      }
-
-      /* If the data model is not changing, it is an error if the
-         jvmpath does not exist */
-      if (wanted == running) {
-        /* Find out where the JRE is that we will be using. */
-        if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) {
-          fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n");
-          exit(2);
-        }
-
-        /* Find the specified JVM type */
-        if (ReadKnownVMs(jrepath, arch, JNI_FALSE) < 1) {
-          fprintf(stderr, "Error: no known VMs. (check for corrupt jvm.cfg file)\n");
-          exit(1);
-        }
-
-        jvmpath[0] = '\0';
-        jvmtype = CheckJvmType(_argcp, _argvp, JNI_FALSE);
-
-        if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch )) {
-          fprintf(stderr, "Error: no `%s' JVM at `%s'.\n", jvmtype, jvmpath);
-          exit(4);
-        }
-      } else {  /* do the same speculatively or exit */
-#ifdef DUAL_MODE
-        if (running != wanted) {
-          /* Find out where the JRE is that we will be using. */
-          if (!GetJREPath(jrepath, so_jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH), JNI_TRUE)) {
-            goto EndDataModelSpeculate;
-          }
-
-          /*
-           * Read in jvm.cfg for target data model and process vm
-           * selection options.
-           */
-          if (ReadKnownVMs(jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH), JNI_TRUE) < 1) {
-            goto EndDataModelSpeculate;
-          }
-          jvmpath[0] = '\0';
-          jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE);
-          /* exec child can do error checking on the existence of the path */
-          jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath,
-                                     ((wanted==64)?BIG_ARCH:SMALL_ARCH));
-
-        }
-      EndDataModelSpeculate: /* give up and let other code report error message */
-        ;
-#else
-        fprintf(stderr, "Running a %d-bit JVM is not supported on this platform.\n", wanted);
-        exit(1);
-#endif
-      }
-
-      /*
-       * We will set the LD_LIBRARY_PATH as follows:
-       *
-       *     o          $JVMPATH (directory portion only)
-       *     o          $JRE/lib/$ARCH
-       *     o          $JRE/../lib/$ARCH
-       *
-       * followed by the user's previous effective LD_LIBRARY_PATH, if
-       * any.
-       */
-
-#ifdef __sun
-      /*
-       * Starting in Solaris 7, ld.so.1 supports three LD_LIBRARY_PATH
-       * variables:
-       *
-       * 1. LD_LIBRARY_PATH -- used for 32 and 64 bit searches if
-       * data-model specific variables are not set.
-       *
-       * 2. LD_LIBRARY_PATH_64 -- overrides and replaces LD_LIBRARY_PATH
-       * for 64-bit binaries.
-       *
-       * 3. LD_LIBRARY_PATH_32 -- overrides and replaces LD_LIBRARY_PATH
-       * for 32-bit binaries.
-       *
-       * The vm uses LD_LIBRARY_PATH to set the java.library.path system
-       * property.  To shield the vm from the complication of multiple
-       * LD_LIBRARY_PATH variables, if the appropriate data model
-       * specific variable is set, we will act as if LD_LIBRARY_PATH had
-       * the value of the data model specific variant and the data model
-       * specific variant will be unset.  Note that the variable for the
-       * *wanted* data model must be used (if it is set), not simply the
-       * current running data model.
-       */
-
-      switch(wanted) {
-      case 0:
-        if(running == 32) {
-          dmpath = getenv("LD_LIBRARY_PATH_32");
-          wanted = 32;
-        }
-        else {
-          dmpath = getenv("LD_LIBRARY_PATH_64");
-          wanted = 64;
-        }
-        break;
-
-      case 32:
-        dmpath = getenv("LD_LIBRARY_PATH_32");
-        break;
-
-      case 64:
-        dmpath = getenv("LD_LIBRARY_PATH_64");
-        break;
-
-      default:
-        fprintf(stderr, "Improper value at line %d.", __LINE__);
-        exit(1); /* unknown value in wanted */
-        break;
-      }
-
-      /*
-       * If dmpath is NULL, the relevant data model specific variable is
-       * not set and normal LD_LIBRARY_PATH should be used.
-       */
-      if( dmpath == NULL) {
-        runpath = getenv("LD_LIBRARY_PATH");
-      }
-      else {
-        runpath = dmpath;
-      }
-#else
-      /*
-       * If not on Solaris, assume only a single LD_LIBRARY_PATH
-       * variable.
-       */
-      runpath = getenv("LD_LIBRARY_PATH");
-#endif /* __sun */
-
-#ifdef __linux
-      /*
-       * On linux, if a binary is running as sgid or suid, glibc sets
-       * LD_LIBRARY_PATH to the empty string for security purposes.  (In
-       * contrast, on Solaris the LD_LIBRARY_PATH variable for a
-       * privileged binary does not lose its settings; but the dynamic
-       * linker does apply more scrutiny to the path.) The launcher uses
-       * the value of LD_LIBRARY_PATH to prevent an exec loop.
-       * Therefore, if we are running sgid or suid, this function's
-       * setting of LD_LIBRARY_PATH will be ineffective and we should
-       * return from the function now.  Getting the right libraries to
-       * be found must be handled through other mechanisms.
-       */
-      if((getgid() != getegid()) || (getuid() != geteuid()) ) {
-        return;
-      }
-#endif
-
-      /* runpath contains current effective LD_LIBRARY_PATH setting */
-
-      jvmpath = strdup(jvmpath);
-      new_runpath = MemAlloc( ((runpath!=NULL)?strlen(runpath):0) +
-                              2*strlen(jrepath) + 2*strlen(arch) +
-                              strlen(jvmpath) + 52);
-      newpath = new_runpath + strlen("LD_LIBRARY_PATH=");
-
-
-      /*
-       * Create desired LD_LIBRARY_PATH value for target data model.
-       */
-      {
-        /* remove the name of the .so from the JVM path */
-        lastslash = strrchr(jvmpath, '/');
-        if (lastslash)
-          *lastslash = '\0';
-
-
-        /* jvmpath, ((running != wanted)?((wanted==64)?"/"BIG_ARCH:"/.."):""), */
-
-        sprintf(new_runpath, "LD_LIBRARY_PATH="
-                "%s:"
-                "%s/lib/%s:"
-                "%s/../lib/%s",
-                jvmpath,
-#ifdef DUAL_MODE
-                jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH),
-                jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH)
-#else
-                jrepath, arch,
-                jrepath, arch
-#endif
-                );
-
-
-        /*
-         * Check to make sure that the prefix of the current path is the
-         * desired environment variable setting.
-         */
-        if (runpath != NULL &&
-            strncmp(newpath, runpath, strlen(newpath))==0 &&
-            (runpath[strlen(newpath)] == 0 || runpath[strlen(newpath)] == ':') &&
-            (running == wanted) /* data model does not have to be changed */
-#ifdef __sun
-            && (dmpath == NULL)    /* data model specific variables not set  */
-#endif
-            ) {
-
-          return;
-
-        }
-      }
-
-      /*
-       * Place the desired environment setting onto the prefix of
-       * LD_LIBRARY_PATH.  Note that this prevents any possible infinite
-       * loop of execv() because we test for the prefix, above.
-       */
-      if (runpath != 0) {
-        strcat(new_runpath, ":");
-        strcat(new_runpath, runpath);
-      }
-
-      if( putenv(new_runpath) != 0) {
-        exit(1); /* problem allocating memory; LD_LIBRARY_PATH not set
-                    properly */
-      }
-
-      /*
-       * Unix systems document that they look at LD_LIBRARY_PATH only
-       * once at startup, so we have to re-exec the current executable
-       * to get the changed environment variable to have an effect.
-       */
-
-#ifdef __sun
-      /*
-       * If dmpath is not NULL, remove the data model specific string
-       * in the environment for the exec'ed child.
-       */
-
-      if( dmpath != NULL)
-        (void)UnsetEnv((wanted==32)?"LD_LIBRARY_PATH_32":"LD_LIBRARY_PATH_64");
-#endif
-
-      newenvp = environ;
-
-      {
-        char *newexec = execname;
-#ifdef DUAL_MODE
-        /*
-         * If the data model is being changed, the path to the
-         * executable must be updated accordingly; the executable name
-         * and directory the executable resides in are separate.  In the
-         * case of 32 => 64, the new bits are assumed to reside in, e.g.
-         * "olddir/BIGARCH/execname"; in the case of 64 => 32,
-         * the bits are assumed to be in "olddir/../execname".  For example,
-         *
-         * olddir/sparcv9/execname
-         * olddir/amd64/execname
-         *
-         * for Solaris SPARC and Linux amd64, respectively.
-         */
-
-        if (running != wanted) {
-          char *oldexec = strcpy(MemAlloc(strlen(execname) + 1), execname);
-          char *olddir = oldexec;
-          char *oldbase = strrchr(oldexec, '/');
-
-
-          newexec = MemAlloc(strlen(execname) + 20);
-          *oldbase++ = 0;
-          sprintf(newexec, "%s/%s/%s", olddir,
-                  ((wanted==64) ? BIG_ARCH : ".."), oldbase);
-          argv[0] = newexec;
-        }
-#endif
-
-        execve(newexec, argv, newenvp);
-        perror("execve()");
-
-        fprintf(stderr, "Error trying to exec %s.\n", newexec);
-        fprintf(stderr, "Check if file exists and permissions are set correctly.\n");
-
-#ifdef DUAL_MODE
-        if (running != wanted) {
-          fprintf(stderr, "Failed to start a %d-bit JVM process from a %d-bit JVM.\n",
-                  wanted, running);
-#  ifdef __sun
-
-#    ifdef __sparc
-          fprintf(stderr, "Verify all necessary J2SE components have been installed.\n" );
-          fprintf(stderr,
-                  "(Solaris SPARC 64-bit components must be installed after 32-bit components.)\n" );
-#    else
-          fprintf(stderr, "Either 64-bit processes are not supported by this platform\n");
-          fprintf(stderr, "or the 64-bit components have not been installed.\n");
-#    endif
-        }
-#  endif
-#endif
-
-      }
-
-      exit(1);
-    }
-
-#else  /* ifndef GAMMA */
-
-  /* gamma launcher is simpler in that it doesn't handle VM flavors, data  */
-  /* model, LD_LIBRARY_PATH, etc. Assuming everything is set-up correctly  */
-  /* all we need to do here is to return correct path names. See also      */
-  /* GetJVMPath() and GetApplicationHome().                                */
-
-  { char *arch = (char *)GetArch(); /* like sparc or sparcv9 */
-    char *p;
-
-    if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) {
-      fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n");
-      exit(2);
-    }
-
-    if (!GetJVMPath(jrepath, NULL, jvmpath, so_jvmpath, arch )) {
-      fprintf(stderr, "Error: no JVM at `%s'.\n", jvmpath);
-      exit(4);
-    }
-  }
-
-#endif  /* ifndef GAMMA */
-}
-
-
-/*
- * On Solaris VM choosing is done by the launcher (java.c).
- */
-static jboolean
-GetJVMPath(const char *jrepath, const char *jvmtype,
-           char *jvmpath, jint jvmpathsize, char * arch)
-{
-    struct stat s;
-
-#ifndef GAMMA
-    if (strchr(jvmtype, '/')) {
-        sprintf(jvmpath, "%s/" JVM_DLL, jvmtype);
-    } else {
-        sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
-    }
-#else
-    /* For gamma launcher, JVM is either built-in or in the same directory. */
-    /* Either way we return "<exe_path>/libjvm.so" where <exe_path> is the  */
-    /* directory where gamma launcher is located.                           */
-
-    char *p;
-
-    snprintf(jvmpath, jvmpathsize, "%s", GetExecname());
-    p = strrchr(jvmpath, '/');
-    if (p) {
-       /* replace executable name with libjvm.so */
-       snprintf(p + 1, jvmpathsize - (p + 1 - jvmpath), "%s", JVM_DLL);
-    } else {
-       /* this case shouldn't happen */
-       snprintf(jvmpath, jvmpathsize, "%s", JVM_DLL);
-    }
-#endif
-
-    if (_launcher_debug)
-      printf("Does `%s' exist ... ", jvmpath);
-
-    if (stat(jvmpath, &s) == 0) {
-        if (_launcher_debug)
-          printf("yes.\n");
-        return JNI_TRUE;
-    } else {
-        if (_launcher_debug)
-          printf("no.\n");
-        return JNI_FALSE;
-    }
-}
-
-/*
- * Find path to JRE based on .exe's location or registry settings.
- */
-static jboolean
-GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative)
-{
-    char libjava[MAXPATHLEN];
-
-    if (GetApplicationHome(path, pathsize)) {
-        /* Is JRE co-located with the application? */
-        sprintf(libjava, "%s/lib/%s/" JAVA_DLL, path, arch);
-        if (access(libjava, F_OK) == 0) {
-            goto found;
-        }
-
-        /* Does the app ship a private JRE in <apphome>/jre directory? */
-        sprintf(libjava, "%s/jre/lib/%s/" JAVA_DLL, path, arch);
-        if (access(libjava, F_OK) == 0) {
-            strcat(path, "/jre");
-            goto found;
-        }
-    }
-
-    if (!speculative)
-      fprintf(stderr, "Error: could not find " JAVA_DLL "\n");
-    return JNI_FALSE;
-
- found:
-    if (_launcher_debug)
-      printf("JRE path is %s\n", path);
-    return JNI_TRUE;
-}
-
-jboolean
-LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
-{
-#ifdef GAMMA
-    /* JVM is directly linked with gamma launcher; no dlopen() */
-    ifn->CreateJavaVM = JNI_CreateJavaVM;
-    ifn->GetDefaultJavaVMInitArgs = JNI_GetDefaultJavaVMInitArgs;
-    return JNI_TRUE;
-#else
-    Dl_info dlinfo;
-    void *libjvm;
-
-    if (_launcher_debug) {
-        printf("JVM path is %s\n", jvmpath);
-    }
-
-    libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
-    if (libjvm == NULL) {
-#if defined(__sparc) && !defined(_LP64) /* i.e. 32-bit sparc */
-      FILE * fp;
-      Elf32_Ehdr elf_head;
-      int count;
-      int location;
-
-      fp = fopen(jvmpath, "r");
-      if(fp == NULL)
-        goto error;
-
-      /* read in elf header */
-      count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp);
-      fclose(fp);
-      if(count < 1)
-        goto error;
-
-      /*
-       * Check for running a server vm (compiled with -xarch=v8plus)
-       * on a stock v8 processor.  In this case, the machine type in
-       * the elf header would not be included the architecture list
-       * provided by the isalist command, which is turn is gotten from
-       * sysinfo.  This case cannot occur on 64-bit hardware and thus
-       * does not have to be checked for in binaries with an LP64 data
-       * model.
-       */
-      if(elf_head.e_machine == EM_SPARC32PLUS) {
-        char buf[257];  /* recommended buffer size from sysinfo man
-                           page */
-        long length;
-        char* location;
-
-        length = sysinfo(SI_ISALIST, buf, 257);
-        if(length > 0) {
-          location = strstr(buf, "sparcv8plus ");
-          if(location == NULL) {
-            fprintf(stderr, "SPARC V8 processor detected; Server compiler requires V9 or better.\n");
-            fprintf(stderr, "Use Client compiler on V8 processors.\n");
-            fprintf(stderr, "Could not create the Java virtual machine.\n");
-            return JNI_FALSE;
-          }
-        }
-      }
-#endif
-      fprintf(stderr, "dl failure on line %d", __LINE__);
-      goto error;
-    }
-
-    ifn->CreateJavaVM = (CreateJavaVM_t)
-      dlsym(libjvm, "JNI_CreateJavaVM");
-    if (ifn->CreateJavaVM == NULL)
-        goto error;
-
-    ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
-        dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");
-    if (ifn->GetDefaultJavaVMInitArgs == NULL)
-      goto error;
-
-    return JNI_TRUE;
-
-error:
-    fprintf(stderr, "Error: failed %s, because %s\n", jvmpath, dlerror());
-    return JNI_FALSE;
-#endif /* GAMMA */
-}
-
-/*
- * Get the path to the file that has the usage message for -X options.
- */
-void
-GetXUsagePath(char *buf, jint bufsize)
-{
-    static const char Xusage_txt[] = "/Xusage.txt";
-    Dl_info dlinfo;
-
-    /* we use RTLD_NOW because of problems with ld.so.1 and green threads */
-    dladdr(dlsym(dlopen(JVM_DLL, RTLD_NOW), "JNI_CreateJavaVM"), &dlinfo);
-    strncpy(buf, (char *)dlinfo.dli_fname, bufsize - sizeof(Xusage_txt));
-
-    buf[bufsize-1] = '\0';
-    strcpy(strrchr(buf, '/'), Xusage_txt);
-}
-
-/*
- * If app is "/foo/bin/javac", or "/foo/bin/sparcv9/javac" then put
- * "/foo" into buf.
- */
-jboolean
-GetApplicationHome(char *buf, jint bufsize)
-{
-#ifdef __linux__
-    char *execname = GetExecname();
-    if (execname) {
-        strncpy(buf, execname, bufsize-1);
-        buf[bufsize-1] = '\0';
-    } else {
-        return JNI_FALSE;
-    }
-#else
-    Dl_info dlinfo;
-
-    dladdr((void *)GetApplicationHome, &dlinfo);
-    if (realpath(dlinfo.dli_fname, buf) == NULL) {
-        fprintf(stderr, "Error: realpath(`%s') failed.\n", dlinfo.dli_fname);
-        return JNI_FALSE;
-    }
-#endif
-
-#ifdef GAMMA
-    {
-      /* gamma launcher uses JAVA_HOME environment variable to find JDK/JRE */
-      char* java_home_var = getenv("JAVA_HOME");
-      if (java_home_var == NULL) {
-        printf("JAVA_HOME must point to a valid JDK/JRE to run gamma\n");
-        return JNI_FALSE;
-      }
-      snprintf(buf, bufsize, "%s", java_home_var);
-    }
-#else
-    if (strrchr(buf, '/') == 0) {
-        buf[0] = '\0';
-        return JNI_FALSE;
-    }
-    *(strrchr(buf, '/')) = '\0';        /* executable file      */
-    if (strlen(buf) < 4 || strrchr(buf, '/') == 0) {
-        buf[0] = '\0';
-        return JNI_FALSE;
-    }
-    if (strcmp("/bin", buf + strlen(buf) - 4) != 0)
-        *(strrchr(buf, '/')) = '\0';    /* sparcv9 or amd64     */
-    if (strlen(buf) < 4 || strcmp("/bin", buf + strlen(buf) - 4) != 0) {
-        buf[0] = '\0';
-        return JNI_FALSE;
-    }
-    *(strrchr(buf, '/')) = '\0';        /* bin                  */
-#endif /* GAMMA */
-
-    return JNI_TRUE;
-}
-
-
-/*
- * Return true if the named program exists
- */
-static int
-ProgramExists(char *name)
-{
-    struct stat sb;
-    if (stat(name, &sb) != 0) return 0;
-    if (S_ISDIR(sb.st_mode)) return 0;
-    return (sb.st_mode & S_IEXEC) != 0;
-}
-
-
-/*
- * Find a command in a directory, returning the path.
- */
-static char *
-Resolve(char *indir, char *cmd)
-{
-    char name[PATH_MAX + 2], *real;
-
-    if ((strlen(indir) + strlen(cmd) + 1)  > PATH_MAX) return 0;
-    sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd);
-    if (!ProgramExists(name)) return 0;
-    real = MemAlloc(PATH_MAX + 2);
-    if (!realpath(name, real))
-        strcpy(real, name);
-    return real;
-}
-
-
-/*
- * Find a path for the executable
- */
-static char *
-FindExecName(char *program)
-{
-    char cwdbuf[PATH_MAX+2];
-    char *path;
-    char *tmp_path;
-    char *f;
-    char *result = NULL;
-
-    /* absolute path? */
-    if (*program == FILE_SEPARATOR ||
-        (FILE_SEPARATOR=='\\' && strrchr(program, ':')))
-        return Resolve("", program+1);
-
-    /* relative path? */
-    if (strrchr(program, FILE_SEPARATOR) != 0) {
-        char buf[PATH_MAX+2];
-        return Resolve(getcwd(cwdbuf, sizeof(cwdbuf)), program);
-    }
-
-    /* from search path? */
-    path = getenv("PATH");
-    if (!path || !*path) path = ".";
-    tmp_path = MemAlloc(strlen(path) + 2);
-    strcpy(tmp_path, path);
-
-    for (f=tmp_path; *f && result==0; ) {
-        char *s = f;
-        while (*f && (*f != PATH_SEPARATOR)) ++f;
-        if (*f) *f++ = 0;
-        if (*s == FILE_SEPARATOR)
-            result = Resolve(s, program);
-        else {
-            /* relative path element */
-            char dir[2*PATH_MAX];
-            sprintf(dir, "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)),
-                    FILE_SEPARATOR, s);
-            result = Resolve(dir, program);
-        }
-        if (result != 0) break;
-    }
-
-    free(tmp_path);
-    return result;
-}
-
-
-/* Store the name of the executable once computed */
-static char *execname = NULL;
-
-/*
- * Compute the name of the executable
- *
- * In order to re-exec securely we need the absolute path of the
- * executable. On Solaris getexecname(3c) may not return an absolute
- * path so we use dladdr to get the filename of the executable and
- * then use realpath to derive an absolute path. From Solaris 9
- * onwards the filename returned in DL_info structure from dladdr is
- * an absolute pathname so technically realpath isn't required.
- * On Linux we read the executable name from /proc/self/exe.
- * As a fallback, and for platforms other than Solaris and Linux,
- * we use FindExecName to compute the executable name.
- */
-static char *
-SetExecname(char **argv)
-{
-    char* exec_path = NULL;
-
-    if (execname != NULL)       /* Already determined */
-        return (execname);
-
-#if defined(__sun)
-    {
-        Dl_info dlinfo;
-        if (dladdr((void*)&SetExecname, &dlinfo)) {
-            char *resolved = (char*)MemAlloc(PATH_MAX+1);
-            if (resolved != NULL) {
-                exec_path = realpath(dlinfo.dli_fname, resolved);
-                if (exec_path == NULL) {
-                    free(resolved);
-                }
-            }
-        }
-    }
-#elif defined(__linux__)
-    {
-        const char* self = "/proc/self/exe";
-        char buf[PATH_MAX+1];
-        int len = readlink(self, buf, PATH_MAX);
-        if (len >= 0) {
-            buf[len] = '\0';            /* readlink doesn't nul terminate */
-            exec_path = strdup(buf);
-        }
-    }
-#else /* !__sun && !__linux */
-    {
-        /* Not implemented */
-    }
-#endif
-
-    if (exec_path == NULL) {
-        exec_path = FindExecName(argv[0]);
-    }
-    execname = exec_path;
-    return exec_path;
-}
-
-/*
- * Return the name of the executable.  Used in java_md.c to find the JRE area.
- */
-static char *
-GetExecname() {
-  return execname;
-}
-
-void ReportErrorMessage(char * message, jboolean always) {
-  if (always) {
-    fprintf(stderr, "%s\n", message);
-  }
-}
-
-void ReportErrorMessage2(char * format, char * string, jboolean always) {
-  if (always) {
-    fprintf(stderr, format, string);
-    fprintf(stderr, "\n");
-  }
-}
-
-void  ReportExceptionDescription(JNIEnv * env) {
-  (*env)->ExceptionDescribe(env);
-}
-
-/*
- * Return JNI_TRUE for an option string that has no effect but should
- * _not_ be passed on to the vm; return JNI_FALSE otherwise.  On
- * Solaris SPARC, this screening needs to be done if:
- * 1) LD_LIBRARY_PATH does _not_ need to be reset and
- * 2) -d32 or -d64 is passed to a binary with a matching data model
- *    (the exec in SetLibraryPath removes -d<n> options and points the
- *    exec to the proper binary).  When this exec is not done, these options
- *    would end up getting passed onto the vm.
- */
-jboolean RemovableMachineDependentOption(char * option) {
-  /*
-   * Unconditionally remove both -d32 and -d64 options since only
-   * the last such options has an effect; e.g.
-   * java -d32 -d64 -d32 -version
-   * is equivalent to
-   * java -d32 -version
-   */
-
-  if( (strcmp(option, "-d32")  == 0 ) ||
-      (strcmp(option, "-d64")  == 0 ))
-    return JNI_TRUE;
-  else
-    return JNI_FALSE;
-}
-
-void PrintMachineDependentOptions() {
-      fprintf(stdout,
-        "    -d32          use a 32-bit data model if available\n"
-        "\n"
-        "    -d64          use a 64-bit data model if available\n");
-      return;
-}
-
-#ifndef GAMMA  /* gamma launcher does not have ergonomics */
-
-/*
- * The following methods (down to ServerClassMachine()) answer
- * the question about whether a machine is a "server-class"
- * machine.  A server-class machine is loosely defined as one
- * with 2 or more processors and 2 gigabytes or more physical
- * memory.  The definition of a processor is a physical package,
- * not a hyperthreaded chip masquerading as a multi-processor.
- * The definition of memory is also somewhat fuzzy, since x86
- * machines seem not to report all the memory in their DIMMs, we
- * think because of memory mapping of graphics cards, etc.
- *
- * This code is somewhat more confused with #ifdef's than we'd
- * like because this file is used by both Solaris and Linux
- * platforms, and so needs to be parameterized for SPARC and
- * i586 hardware.  The other Linux platforms (amd64 and ia64)
- * don't even ask this question, because they only come with
- * server JVMs.  */
-
-# define KB (1024UL)
-# define MB (1024UL * KB)
-# define GB (1024UL * MB)
-
-/* Compute physical memory by asking the OS */
-uint64_t
-physical_memory(void) {
-  const uint64_t pages     = (uint64_t) sysconf(_SC_PHYS_PAGES);
-  const uint64_t page_size = (uint64_t) sysconf(_SC_PAGESIZE);
-  const uint64_t result    = pages * page_size;
-# define UINT64_FORMAT "%" PRIu64
-
-  if (_launcher_debug) {
-    printf("pages: " UINT64_FORMAT
-           "  page_size: " UINT64_FORMAT
-           "  physical memory: " UINT64_FORMAT " (%.3fGB)\n",
-           pages, page_size, result, result / (double) GB);
-  }
-  return result;
-}
-
-#if defined(__sun) && defined(__sparc)
-
-/* Methods for solaris-sparc: these are easy. */
-
-/* Ask the OS how many processors there are. */
-unsigned long
-physical_processors(void) {
-  const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
-
-  if (_launcher_debug) {
-    printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
-  }
-  return sys_processors;
-}
-
-/* The solaris-sparc version of the "server-class" predicate. */
-jboolean
-solaris_sparc_ServerClassMachine(void) {
-  jboolean            result            = JNI_FALSE;
-  /* How big is a server class machine? */
-  const unsigned long server_processors = 2UL;
-  const uint64_t      server_memory     = 2UL * GB;
-  const uint64_t      actual_memory     = physical_memory();
-
-  /* Is this a server class machine? */
-  if (actual_memory >= server_memory) {
-    const unsigned long actual_processors = physical_processors();
-    if (actual_processors >= server_processors) {
-      result = JNI_TRUE;
-    }
-  }
-  if (_launcher_debug) {
-    printf("solaris_" ARCH "_ServerClassMachine: %s\n",
-           (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE"));
-  }
-  return result;
-}
-
-#endif /* __sun && __sparc */
-
-#if defined(__sun) && defined(i586)
-
-/*
- * A utility method for asking the CPU about itself.
- * There's a corresponding version of linux-i586
- * because the compilers are different.
- */
-void
-get_cpuid(uint32_t arg,
-          uint32_t* eaxp,
-          uint32_t* ebxp,
-          uint32_t* ecxp,
-          uint32_t* edxp) {
-#ifdef _LP64
-  asm(
-  /* rbx is a callee-saved register */
-      " movq    %rbx, %r11  \n"
-  /* rdx and rcx are 3rd and 4th argument registers */
-      " movq    %rdx, %r10  \n"
-      " movq    %rcx, %r9   \n"
-      " movl    %edi, %eax  \n"
-      " cpuid               \n"
-      " movl    %eax, (%rsi)\n"
-      " movl    %ebx, (%r10)\n"
-      " movl    %ecx, (%r9) \n"
-      " movl    %edx, (%r8) \n"
-  /* Restore rbx */
-      " movq    %r11, %rbx");
-#else
-  /* EBX is a callee-saved register */
-  asm(" pushl   %ebx");
-  /* Need ESI for storing through arguments */
-  asm(" pushl   %esi");
-  asm(" movl    8(%ebp), %eax   \n"
-      " cpuid                   \n"
-      " movl    12(%ebp), %esi  \n"
-      " movl    %eax, (%esi)    \n"
-      " movl    16(%ebp), %esi  \n"
-      " movl    %ebx, (%esi)    \n"
-      " movl    20(%ebp), %esi  \n"
-      " movl    %ecx, (%esi)    \n"
-      " movl    24(%ebp), %esi  \n"
-      " movl    %edx, (%esi)      ");
-  /* Restore ESI and EBX */
-  asm(" popl    %esi");
-  /* Restore EBX */
-  asm(" popl    %ebx");
-#endif
-}
-
-#endif /* __sun && i586 */
-
-#if defined(__linux__) && defined(i586)
-
-/*
- * A utility method for asking the CPU about itself.
- * There's a corresponding version of solaris-i586
- * because the compilers are different.
- */
-void
-get_cpuid(uint32_t arg,
-          uint32_t* eaxp,
-          uint32_t* ebxp,
-          uint32_t* ecxp,
-          uint32_t* edxp) {
-#ifdef _LP64
-  __asm__ volatile (/* Instructions */
-                    "   movl    %4, %%eax  \n"
-                    "   cpuid              \n"
-                    "   movl    %%eax, (%0)\n"
-                    "   movl    %%ebx, (%1)\n"
-                    "   movl    %%ecx, (%2)\n"
-                    "   movl    %%edx, (%3)\n"
-                    : /* Outputs */
-                    : /* Inputs */
-                    "r" (eaxp),
-                    "r" (ebxp),
-                    "r" (ecxp),
-                    "r" (edxp),
-                    "r" (arg)
-                    : /* Clobbers */
-                    "%rax", "%rbx", "%rcx", "%rdx", "memory"
-                    );
-#else
-  uint32_t value_of_eax = 0;
-  uint32_t value_of_ebx = 0;
-  uint32_t value_of_ecx = 0;
-  uint32_t value_of_edx = 0;
-  __asm__ volatile (/* Instructions */
-                        /* ebx is callee-save, so push it */
-                        /* even though it's in the clobbers section */
-                    "   pushl   %%ebx      \n"
-                    "   movl    %4, %%eax  \n"
-                    "   cpuid              \n"
-                    "   movl    %%eax, %0  \n"
-                    "   movl    %%ebx, %1  \n"
-                    "   movl    %%ecx, %2  \n"
-                    "   movl    %%edx, %3  \n"
-                        /* restore ebx */
-                    "   popl    %%ebx      \n"
-
-                    : /* Outputs */
-                    "=m" (value_of_eax),
-                    "=m" (value_of_ebx),
-                    "=m" (value_of_ecx),
-                    "=m" (value_of_edx)
-                    : /* Inputs */
-                    "m" (arg)
-                    : /* Clobbers */
-                    "%eax", "%ebx", "%ecx", "%edx"
-                    );
-  *eaxp = value_of_eax;
-  *ebxp = value_of_ebx;
-  *ecxp = value_of_ecx;
-  *edxp = value_of_edx;
-#endif
-}
-
-#endif /* __linux__ && i586 */
-
-#ifdef i586
-/*
- * Routines shared by solaris-i586 and linux-i586.
- */
-
-enum HyperThreadingSupport_enum {
-  hts_supported        =  1,
-  hts_too_soon_to_tell =  0,
-  hts_not_supported    = -1,
-  hts_not_pentium4     = -2,
-  hts_not_intel        = -3
-};
-typedef enum HyperThreadingSupport_enum HyperThreadingSupport;
-
-/* Determine if hyperthreading is supported */
-HyperThreadingSupport
-hyperthreading_support(void) {
-  HyperThreadingSupport result = hts_too_soon_to_tell;
-  /* Bits 11 through 8 is family processor id */
-# define FAMILY_ID_SHIFT 8
-# define FAMILY_ID_MASK 0xf
-  /* Bits 23 through 20 is extended family processor id */
-# define EXT_FAMILY_ID_SHIFT 20
-# define EXT_FAMILY_ID_MASK 0xf
-  /* Pentium 4 family processor id */
-# define PENTIUM4_FAMILY_ID 0xf
-  /* Bit 28 indicates Hyper-Threading Technology support */
-# define HT_BIT_SHIFT 28
-# define HT_BIT_MASK 1
-  uint32_t vendor_id[3] = { 0U, 0U, 0U };
-  uint32_t value_of_eax = 0U;
-  uint32_t value_of_edx = 0U;
-  uint32_t dummy        = 0U;
-
-  /* Yes, this is supposed to be [0], [2], [1] */
-  get_cpuid(0, &dummy, &vendor_id[0], &vendor_id[2], &vendor_id[1]);
-  if (_launcher_debug) {
-    printf("vendor: %c %c %c %c %c %c %c %c %c %c %c %c \n",
-           ((vendor_id[0] >>  0) & 0xff),
-           ((vendor_id[0] >>  8) & 0xff),
-           ((vendor_id[0] >> 16) & 0xff),
-           ((vendor_id[0] >> 24) & 0xff),
-           ((vendor_id[1] >>  0) & 0xff),
-           ((vendor_id[1] >>  8) & 0xff),
-           ((vendor_id[1] >> 16) & 0xff),
-           ((vendor_id[1] >> 24) & 0xff),
-           ((vendor_id[2] >>  0) & 0xff),
-           ((vendor_id[2] >>  8) & 0xff),
-           ((vendor_id[2] >> 16) & 0xff),
-           ((vendor_id[2] >> 24) & 0xff));
-  }
-  get_cpuid(1, &value_of_eax, &dummy, &dummy, &value_of_edx);
-  if (_launcher_debug) {
-    printf("value_of_eax: 0x%x  value_of_edx: 0x%x\n",
-           value_of_eax, value_of_edx);
-  }
-  if ((((value_of_eax >> FAMILY_ID_SHIFT) & FAMILY_ID_MASK) == PENTIUM4_FAMILY_ID) ||
-      (((value_of_eax >> EXT_FAMILY_ID_SHIFT) & EXT_FAMILY_ID_MASK) != 0)) {
-    if ((((vendor_id[0] >>  0) & 0xff) == 'G') &&
-        (((vendor_id[0] >>  8) & 0xff) == 'e') &&
-        (((vendor_id[0] >> 16) & 0xff) == 'n') &&
-        (((vendor_id[0] >> 24) & 0xff) == 'u') &&
-        (((vendor_id[1] >>  0) & 0xff) == 'i') &&
-        (((vendor_id[1] >>  8) & 0xff) == 'n') &&
-        (((vendor_id[1] >> 16) & 0xff) == 'e') &&
-        (((vendor_id[1] >> 24) & 0xff) == 'I') &&
-        (((vendor_id[2] >>  0) & 0xff) == 'n') &&
-        (((vendor_id[2] >>  8) & 0xff) == 't') &&
-        (((vendor_id[2] >> 16) & 0xff) == 'e') &&
-        (((vendor_id[2] >> 24) & 0xff) == 'l')) {
-      if (((value_of_edx >> HT_BIT_SHIFT) & HT_BIT_MASK) == HT_BIT_MASK) {
-        if (_launcher_debug) {
-          printf("Hyperthreading supported\n");
-        }
-        result = hts_supported;
-      } else {
-        if (_launcher_debug) {
-          printf("Hyperthreading not supported\n");
-        }
-        result = hts_not_supported;
-      }
-    } else {
-      if (_launcher_debug) {
-        printf("Not GenuineIntel\n");
-      }
-      result = hts_not_intel;
-    }
-  } else {
-    if (_launcher_debug) {
-      printf("not Pentium 4 or extended\n");
-    }
-    result = hts_not_pentium4;
-  }
-  return result;
-}
-
-/* Determine how many logical processors there are per CPU */
-unsigned int
-logical_processors_per_package(void) {
-  /*
-   * After CPUID with EAX==1, register EBX bits 23 through 16
-   * indicate the number of logical processors per package
-   */
-# define NUM_LOGICAL_SHIFT 16
-# define NUM_LOGICAL_MASK 0xff
-  unsigned int result                        = 1U;
-  const HyperThreadingSupport hyperthreading = hyperthreading_support();
-
-  if (hyperthreading == hts_supported) {
-    uint32_t value_of_ebx = 0U;
-    uint32_t dummy        = 0U;
-
-    get_cpuid(1, &dummy, &value_of_ebx, &dummy, &dummy);
-    result = (value_of_ebx >> NUM_LOGICAL_SHIFT) & NUM_LOGICAL_MASK;
-    if (_launcher_debug) {
-      printf("logical processors per package: %u\n", result);
-    }
-  }
-  return result;
-}
-
-/* Compute the number of physical processors, not logical processors */
-unsigned long
-physical_processors(void) {
-  const long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
-  unsigned long result      = sys_processors;
-
-  if (_launcher_debug) {
-    printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
-  }
-  if (sys_processors > 1) {
-    unsigned int logical_processors = logical_processors_per_package();
-    if (logical_processors > 1) {
-      result = (unsigned long) sys_processors / logical_processors;
-    }
-  }
-  if (_launcher_debug) {
-    printf("physical processors: %lu\n", result);
-  }
-  return result;
-}
-
-#endif /* i586 */
-
-#if defined(__sun) && defined(i586)
-
-/* The definition of a server-class machine for solaris-i586/amd64 */
-jboolean
-solaris_i586_ServerClassMachine(void) {
-  jboolean            result            = JNI_FALSE;
-  /* How big is a server class machine? */
-  const unsigned long server_processors = 2UL;
-  const uint64_t      server_memory     = 2UL * GB;
-  /*
-   * We seem not to get our full complement of memory.
-   *     We allow some part (1/8?) of the memory to be "missing",
-   *     based on the sizes of DIMMs, and maybe graphics cards.
-   */
-  const uint64_t      missing_memory    = 256UL * MB;
-  const uint64_t      actual_memory     = physical_memory();
-
-  /* Is this a server class machine? */
-  if (actual_memory >= (server_memory - missing_memory)) {
-    const unsigned long actual_processors = physical_processors();
-    if (actual_processors >= server_processors) {
-      result = JNI_TRUE;
-    }
-  }
-  if (_launcher_debug) {
-    printf("solaris_" ARCH "_ServerClassMachine: %s\n",
-           (result == JNI_TRUE ? "true" : "false"));
-  }
-  return result;
-}
-
-#endif /* __sun && i586 */
-
-#if defined(__linux__) && defined(i586)
-
-/* The definition of a server-class machine for linux-i586 */
-jboolean
-linux_i586_ServerClassMachine(void) {
-  jboolean            result            = JNI_FALSE;
-  /* How big is a server class machine? */
-  const unsigned long server_processors = 2UL;
-  const uint64_t      server_memory     = 2UL * GB;
-  /*
-   * We seem not to get our full complement of memory.
-   *     We allow some part (1/8?) of the memory to be "missing",
-   *     based on the sizes of DIMMs, and maybe graphics cards.
-   */
-  const uint64_t      missing_memory    = 256UL * MB;
-  const uint64_t      actual_memory     = physical_memory();
-
-  /* Is this a server class machine? */
-  if (actual_memory >= (server_memory - missing_memory)) {
-    const unsigned long actual_processors = physical_processors();
-    if (actual_processors >= server_processors) {
-      result = JNI_TRUE;
-    }
-  }
-  if (_launcher_debug) {
-    printf("linux_" ARCH "_ServerClassMachine: %s\n",
-           (result == JNI_TRUE ? "true" : "false"));
-  }
-  return result;
-}
-
-#endif /* __linux__ && i586 */
-
-/* Dispatch to the platform-specific definition of "server-class" */
-jboolean
-ServerClassMachine(void) {
-  jboolean result = JNI_FALSE;
-#if   defined(__sun) && defined(__sparc)
-  result = solaris_sparc_ServerClassMachine();
-#elif defined(__sun) && defined(i586)
-  result = solaris_i586_ServerClassMachine();
-#elif defined(__linux__) && defined(i586)
-  result = linux_i586_ServerClassMachine();
-#else
-  if (_launcher_debug) {
-    printf("ServerClassMachine: returns default value of %s\n",
-           (result == JNI_TRUE ? "true" : "false"));
-  }
-#endif
-  return result;
-}
-
-#endif /* ifndef GAMMA */
-
-#ifndef GAMMA /* gamma launcher does not choose JDK/JRE/JVM */
-
-/*
- *      Since using the file system as a registry is a bit risky, perform
- *      additional sanity checks on the identified directory to validate
- *      it as a valid jre/sdk.
- *
- *      Return 0 if the tests fail; otherwise return non-zero (true).
- *
- *      Note that checking for anything more than the existence of an
- *      executable object at bin/java relative to the path being checked
- *      will break the regression tests.
- */
-static int
-CheckSanity(char *path, char *dir)
-{
-    char    buffer[PATH_MAX];
-
-    if (strlen(path) + strlen(dir) + 11 > PATH_MAX)
-        return (0);     /* Silently reject "impossibly" long paths */
-
-    (void)strcat(strcat(strcat(strcpy(buffer, path), "/"), dir), "/bin/java");
-    return ((access(buffer, X_OK) == 0) ? 1 : 0);
-}
-
-/*
- *      Determine if there is an acceptable JRE in the directory dirname.
- *      Upon locating the "best" one, return a fully qualified path to
- *      it. "Best" is defined as the most advanced JRE meeting the
- *      constraints contained in the manifest_info. If no JRE in this
- *      directory meets the constraints, return NULL.
- *
- *      Note that we don't check for errors in reading the directory
- *      (which would be done by checking errno).  This is because it
- *      doesn't matter if we get an error reading the directory, or
- *      we just don't find anything interesting in the directory.  We
- *      just return NULL in either case.
- *
- *      The historical names of j2sdk and j2re were changed to jdk and
- *      jre respecively as part of the 1.5 rebranding effort.  Since the
- *      former names are legacy on Linux, they must be recognized for
- *      all time.  Fortunately, this is a minor cost.
- */
-static char
-*ProcessDir(manifest_info *info, char *dirname)
-{
-    DIR     *dirp;
-    struct dirent *dp;
-    char    *best = NULL;
-    int     offset;
-    int     best_offset = 0;
-    char    *ret_str = NULL;
-    char    buffer[PATH_MAX];
-
-    if ((dirp = opendir(dirname)) == NULL)
-        return (NULL);
-
-    do {
-        if ((dp = readdir(dirp)) != NULL) {
-            offset = 0;
-            if ((strncmp(dp->d_name, "jre", 3) == 0) ||
-                (strncmp(dp->d_name, "jdk", 3) == 0))
-                offset = 3;
-            else if (strncmp(dp->d_name, "j2re", 4) == 0)
-                offset = 4;
-            else if (strncmp(dp->d_name, "j2sdk", 5) == 0)
-                offset = 5;
-            if (offset > 0) {
-                if ((acceptable_release(dp->d_name + offset,
-                    info->jre_version)) && CheckSanity(dirname, dp->d_name))
-                    if ((best == NULL) || (exact_version_id(
-                      dp->d_name + offset, best + best_offset) > 0)) {
-                        if (best != NULL)
-                            free(best);
-                        best = strdup(dp->d_name);
-                        best_offset = offset;
-                    }
-            }
-        }
-    } while (dp != NULL);
-    (void) closedir(dirp);
-    if (best == NULL)
-        return (NULL);
-    else {
-        ret_str = MemAlloc(strlen(dirname) + strlen(best) + 2);
-        ret_str = strcat(strcat(strcpy(ret_str, dirname), "/"), best);
-        free(best);
-        return (ret_str);
-    }
-}
-
-/*
- *      This is the global entry point. It examines the host for the optimal
- *      JRE to be used by scanning a set of directories.  The set of directories
- *      is platform dependent and can be overridden by the environment
- *      variable JAVA_VERSION_PATH.
- *
- *      This routine itself simply determines the set of appropriate
- *      directories before passing control onto ProcessDir().
- */
-char*
-LocateJRE(manifest_info* info)
-{
-    char        *path;
-    char        *home;
-    char        *target = NULL;
-    char        *dp;
-    char        *cp;
-
-    /*
-     * Start by getting JAVA_VERSION_PATH
-     */
-    if (info->jre_restrict_search)
-        path = strdup(system_dir);
-    else if ((path = getenv("JAVA_VERSION_PATH")) != NULL)
-        path = strdup(path);
-    else
-        if ((home = getenv("HOME")) != NULL) {
-            path = (char *)MemAlloc(strlen(home) + 13);
-            path = strcat(strcat(strcat(strcpy(path, home),
-                user_dir), ":"), system_dir);
-        } else
-            path = strdup(system_dir);
-
-    /*
-     * Step through each directory on the path. Terminate the scan with
-     * the first directory with an acceptable JRE.
-     */
-    cp = dp = path;
-    while (dp != NULL) {
-        cp = strchr(dp, (int)':');
-        if (cp != NULL)
-            *cp = (char)NULL;
-        if ((target = ProcessDir(info, dp)) != NULL)
-            break;
-        dp = cp;
-        if (dp != NULL)
-            dp++;
-    }
-    free(path);
-    return (target);
-}
-
-/*
- * Given a path to a jre to execute, this routine checks if this process
- * is indeed that jre.  If not, it exec's that jre.
- *
- * We want to actually check the paths rather than just the version string
- * built into the executable, so that given version specification (and
- * JAVA_VERSION_PATH) will yield the exact same Java environment, regardless
- * of the version of the arbitrary launcher we start with.
- */
-void
-ExecJRE(char *jre, char **argv)
-{
-    char    wanted[PATH_MAX];
-    char    *execname;
-    char    *progname;
-
-    /*
-     * Resolve the real path to the directory containing the selected JRE.
-     */
-    if (realpath(jre, wanted) == NULL) {
-        fprintf(stderr, "Unable to resolve %s\n", jre);
-        exit(1);
-    }
-
-    /*
-     * Resolve the real path to the currently running launcher.
-     */
-    execname = SetExecname(argv);
-    if (execname == NULL) {
-        fprintf(stderr, "Unable to resolve current executable\n");
-        exit(1);
-    }
-
-    /*
-     * If the path to the selected JRE directory is a match to the initial
-     * portion of the path to the currently executing JRE, we have a winner!
-     * If so, just return.
-     */
-    if (strncmp(wanted, execname, strlen(wanted)) == 0)
-        return;                 /* I am the droid you were looking for */
-
-    /*
-     * If this isn't the selected version, exec the selected version.
-     */
-#ifdef JAVA_ARGS  /* javac, jar and friends. */
-    progname = "java";
-#else             /* java, oldjava, javaw and friends */
-#ifdef PROGNAME
-    progname = PROGNAME;
-#else
-    progname = *argv;
-    if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) {
-        progname = s + 1;
-    }
-#endif /* PROGNAME */
-#endif /* JAVA_ARGS */
-
-    /*
-     * This should never happen (because of the selection code in SelectJRE),
-     * but check for "impossibly" long path names just because buffer overruns
-     * can be so deadly.
-     */
-    if (strlen(wanted) + strlen(progname) + 6 > PATH_MAX) {
-        fprintf(stderr, "Path length exceeds maximum length (PATH_MAX)\n");
-        exit(1);
-    }
-
-    /*
-     * Construct the path and exec it.
-     */
-    (void)strcat(strcat(wanted, "/bin/"), progname);
-    argv[0] = progname;
-    if (_launcher_debug) {
-        int i;
-        printf("execv(\"%s\"", wanted);
-        for (i = 0; argv[i] != NULL; i++)
-            printf(", \"%s\"", argv[i]);
-        printf(")\n");
-    }
-    execv(wanted, argv);
-    fprintf(stderr, "Exec of %s failed\n", wanted);
-    exit(1);
-}
-
-#endif /* ifndef GAMMA */
-
-/*
- * "Borrowed" from Solaris 10 where the unsetenv() function is being added
- * to libc thanks to SUSv3 (Standard Unix Specification, version 3). As
- * such, in the fullness of time this will appear in libc on all relevant
- * Solaris/Linux platforms and maybe even the Windows platform.  At that
- * time, this stub can be removed.
- *
- * This implementation removes the environment locking for multithreaded
- * applications.  (We don't have access to these mutexes within libc and
- * the launcher isn't multithreaded.)  Note that what remains is platform
- * independent, because it only relies on attributes that a POSIX environment
- * defines.
- *
- * Returns 0 on success, -1 on failure.
- *
- * Also removed was the setting of errno.  The only value of errno set
- * was EINVAL ("Invalid Argument").
- */
-
-/*
- * s1(environ) is name=value
- * s2(name) is name(not the form of name=value).
- * if names match, return value of 1, else return 0
- */
-static int
-match_noeq(const char *s1, const char *s2)
-{
-        while (*s1 == *s2++) {
-                if (*s1++ == '=')
-                        return (1);
-        }
-        if (*s1 == '=' && s2[-1] == '\0')
-                return (1);
-        return (0);
-}
-
-/*
- * added for SUSv3 standard
- *
- * Delete entry from environ.
- * Do not free() memory!  Other threads may be using it.
- * Keep it around forever.
- */
-static int
-borrowed_unsetenv(const char *name)
-{
-        long    idx;            /* index into environ */
-
-        if (name == NULL || *name == '\0' ||
-            strchr(name, '=') != NULL) {
-                return (-1);
-        }
-
-        for (idx = 0; environ[idx] != NULL; idx++) {
-                if (match_noeq(environ[idx], name))
-                        break;
-        }
-        if (environ[idx] == NULL) {
-                /* name not found but still a success */
-                return (0);
-        }
-        /* squeeze up one entry */
-        do {
-                environ[idx] = environ[idx+1];
-        } while (environ[++idx] != NULL);
-
-        return (0);
-}
-/* --- End of "borrowed" code --- */
-
-/*
- * Wrapper for unsetenv() function.
- */
-int
-UnsetEnv(char *name)
-{
-    return(borrowed_unsetenv(name));
-}
-
-/*
- * The implementation for finding classes from the bootstrap
- * class loader, refer to java.h
- */
-static FindClassFromBootLoader_t *findBootClass = NULL;
-
-jclass
-FindBootStrapClass(JNIEnv *env, const char* classname)
-{
-   if (findBootClass == NULL) {
-       findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT,
-          "JVM_FindClassFromBootLoader");
-       if (findBootClass == NULL) {
-           fprintf(stderr, "Error: could not load method JVM_FindClassFromBootLoader");
-           return NULL;
-       }
-   }
-   return findBootClass(env, classname, JNI_FALSE);
-}
-
--- a/hotspot/src/os/solaris/launcher/java_md.h	Thu Dec 02 20:01:47 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK,
- * search "GAMMA" for gamma specific changes.
- */
-
-#ifndef JAVA_MD_H
-#define JAVA_MD_H
-
-#include <limits.h>
-#include <unistd.h>
-#include <sys/param.h>
-#ifndef GAMMA
-#include "manifest_info.h"
-#endif
-
-#define PATH_SEPARATOR          ':'
-#define FILESEP                 "/"
-#define FILE_SEPARATOR          '/'
-#ifndef MAXNAMELEN
-#define MAXNAMELEN              PATH_MAX
-#endif
-
-#ifdef JAVA_ARGS
-/*
- * ApplicationHome is prepended to each of these entries; the resulting
- * strings are concatenated (separated by PATH_SEPARATOR) and used as the
- * value of -cp option to the launcher.
- */
-#ifndef APP_CLASSPATH
-#define APP_CLASSPATH        { "/lib/tools.jar", "/classes" }
-#endif
-#endif
-
-#ifdef HAVE_GETHRTIME
-/*
- * Support for doing cheap, accurate interval timing.
- */
-#include <sys/time.h>
-#define CounterGet()              (gethrtime()/1000)
-#define Counter2Micros(counts)    (counts)
-#else
-#define CounterGet()              (0)
-#define Counter2Micros(counts)    (1)
-#endif /* HAVE_GETHRTIME */
-
-/*
- * Function prototypes.
- */
-#ifndef GAMMA
-char *LocateJRE(manifest_info* info);
-void ExecJRE(char *jre, char **argv);
-#endif
-int UnsetEnv(char *name);
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/windows/launcher/java_md.c	Thu Dec 02 05:45:54 2010 -0800
@@ -0,0 +1,1465 @@
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <windows.h>
+#include <io.h>
+#include <process.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <jni.h>
+#include "java.h"
+#ifndef GAMMA
+#include "version_comp.h"
+#endif
+
+#define JVM_DLL "jvm.dll"
+#define JAVA_DLL "java.dll"
+#define CRT_DLL "msvcr71.dll"
+
+/*
+ * Prototypes.
+ */
+static jboolean GetPublicJREHome(char *path, jint pathsize);
+static jboolean GetJVMPath(const char *jrepath, const char *jvmtype,
+                           char *jvmpath, jint jvmpathsize);
+static jboolean GetJREPath(char *path, jint pathsize);
+static void EnsureJreInstallation(const char *jrepath);
+
+/* We supports warmup for UI stack that is performed in parallel
+ * to VM initialization.
+ * This helps to improve startup of UI application as warmup phase
+ * might be long due to initialization of OS or hardware resources.
+ * It is not CPU bound and therefore it does not interfere with VM init.
+ * Obviously such warmup only has sense for UI apps and therefore it needs
+ * to be explicitly requested by passing -Dsun.awt.warmup=true property
+ * (this is always the case for plugin/javaws).
+ *
+ * Implementation launches new thread after VM starts and use it to perform
+ * warmup code (platform dependent).
+ * This thread is later reused as AWT toolkit thread as graphics toolkit
+ * often assume that they are used from the same thread they were launched on.
+ *
+ * At the moment we only support warmup for D3D. It only possible on windows
+ * and only if other flags do not prohibit this (e.g. OpenGL support requested).
+ */
+#undef ENABLE_AWT_PRELOAD
+#ifndef JAVA_ARGS /* turn off AWT preloading for javac, jar, etc */
+  #ifdef _X86_ /* for now disable AWT preloading for 64bit */
+    #define ENABLE_AWT_PRELOAD
+  #endif
+#endif
+
+#ifdef ENABLE_AWT_PRELOAD
+/* "AWT was preloaded" flag;
+ * Turned on by AWTPreload().
+ */
+int awtPreloaded = 0;
+
+/* Calls a function with the name specified.
+ * The function must be int(*fn)(void).
+ */
+int AWTPreload(const char *funcName);
+/* Stops AWT preloading. */
+void AWTPreloadStop();
+
+/* D3D preloading */
+/* -1: not initialized; 0: OFF, 1: ON */
+int awtPreloadD3D = -1;
+/* Command line parameter to swith D3D preloading on. */
+#define PARAM_PRELOAD_D3D "-Dsun.awt.warmup"
+/* D3D/OpenGL management parameters (may disable D3D preloading) */
+#define PARAM_NODDRAW "-Dsun.java2d.noddraw"
+#define PARAM_D3D "-Dsun.java2d.d3d"
+#define PARAM_OPENGL "-Dsun.java2d.opengl"
+/* funtion in awt.dll (src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp) */
+#define D3D_PRELOAD_FUNC "preloadD3D"
+
+
+/* Extracts value of a parameter with the specified name
+ * from command line argument (returns pointer in the argument).
+ * Returns NULL if the argument does not contains the parameter.
+ * e.g.:
+ * GetParamValue("theParam", "theParam=value") returns pointer to "value".
+ */
+const char * GetParamValue(const char *paramName, const char *arg) {
+    int nameLen = strlen(paramName);
+    if (strncmp(paramName, arg, nameLen) == 0) {
+        // arg[nameLen] is valid (may contain final NULL)
+        if (arg[nameLen] == '=') {
+            return arg + nameLen + 1;
+        }
+    }
+    return NULL;
+}
+
+/* Checks if commandline argument contains property specified
+ * and analyze it as boolean property (true/false).
+ * Returns -1 if the argument does not contain the parameter;
+ * Returns 1 if the argument contains the parameter and its value is "true";
+ * Returns 0 if the argument contains the parameter and its value is "false".
+ */
+int GetBoolParamValue(const char *paramName, const char *arg) {
+    const char * paramValue = GetParamValue(paramName, arg);
+    if (paramValue != NULL) {
+        if (stricmp(paramValue, "true") == 0) {
+            return 1;
+        }
+        if (stricmp(paramValue, "false") == 0) {
+            return 0;
+        }
+    }
+    return -1;
+}
+#endif /* ENABLE_AWT_PRELOAD */
+
+
+const char *
+GetArch()
+{
+
+#ifdef _M_AMD64
+    return "amd64";
+#elif defined(_M_IA64)
+    return "ia64";
+#else
+    return "i386";
+#endif
+}
+
+/*
+ *
+ */
+void
+CreateExecutionEnvironment(int *_argc,
+                           char ***_argv,
+                           char jrepath[],
+                           jint so_jrepath,
+                           char jvmpath[],
+                           jint so_jvmpath,
+                           char **original_argv) {
+#ifndef GAMMA
+   char * jvmtype;
+
+    /* Find out where the JRE is that we will be using. */
+    if (!GetJREPath(jrepath, so_jrepath)) {
+        ReportErrorMessage("Error: could not find Java SE Runtime Environment.",
+                           JNI_TRUE);
+        exit(2);
+    }
+
+    /* Do this before we read jvm.cfg */
+    EnsureJreInstallation(jrepath);
+
+    /* Find the specified JVM type */
+    if (ReadKnownVMs(jrepath, (char*)GetArch(), JNI_FALSE) < 1) {
+        ReportErrorMessage("Error: no known VMs. (check for corrupt jvm.cfg file)",
+                           JNI_TRUE);
+        exit(1);
+    }
+    jvmtype = CheckJvmType(_argc, _argv, JNI_FALSE);
+
+    jvmpath[0] = '\0';
+    if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath)) {
+        char * message=NULL;
+        const char * format = "Error: no `%s' JVM at `%s'.";
+        message = (char *)JLI_MemAlloc((strlen(format)+strlen(jvmtype)+
+                                    strlen(jvmpath)) * sizeof(char));
+        sprintf(message,format, jvmtype, jvmpath);
+        ReportErrorMessage(message, JNI_TRUE);
+        exit(4);
+    }
+    /* If we got here, jvmpath has been correctly initialized. */
+
+#else  /* ifndef GAMMA */
+
+    /*
+     * gamma launcher is simpler in that it doesn't handle VM flavors, data
+     * model, etc. Assuming everything is set-up correctly
+     * all we need to do here is to return correct path names. See also
+     * GetJVMPath() and GetApplicationHome().
+     */
+
+  {
+    if (!GetJREPath(jrepath, so_jrepath) ) {
+       ReportErrorMessage("Error: could not find Java SE Runtime Environment.",
+                          JNI_TRUE);
+       exit(2);
+    }
+
+    if (!GetJVMPath(jrepath, NULL, jvmpath, so_jvmpath)) {
+       char * message=NULL;
+       const char * format = "Error: no JVM at `%s'.";
+       message = (char *)JLI_MemAlloc((strlen(format)+
+                                       strlen(jvmpath)) * sizeof(char));
+       sprintf(message, format, jvmpath);
+       ReportErrorMessage(message, JNI_TRUE);
+       exit(4);
+    }
+  }
+
+#endif  /* ifndef GAMMA */
+
+}
+
+
+static jboolean
+LoadMSVCRT()
+{
+    // Only do this once
+    static int loaded = 0;
+    char crtpath[MAXPATHLEN];
+
+    if (!loaded) {
+        /*
+         * The Microsoft C Runtime Library needs to be loaded first.  A copy is
+         * assumed to be present in the "JRE path" directory.  If it is not found
+         * there (or "JRE path" fails to resolve), skip the explicit load and let
+         * nature take its course, which is likely to be a failure to execute.
+         */
+        if (GetJREPath(crtpath, MAXPATHLEN)) {
+            (void)strcat(crtpath, "\\bin\\" CRT_DLL);   /* Add crt dll */
+            if (_launcher_debug) {
+                printf("CRT path is %s\n", crtpath);
+            }
+            if (_access(crtpath, 0) == 0) {
+                if (LoadLibrary(crtpath) == 0) {
+                    ReportErrorMessage2("Error loading: %s", crtpath, JNI_TRUE);
+                    return JNI_FALSE;
+                }
+            }
+        }
+        loaded = 1;
+    }
+    return JNI_TRUE;
+}
+
+/*
+ * The preJVMStart is a function in the jkernel.dll, which
+ * performs the final step of synthesizing back the decomposed
+ * modules  (partial install) to the full JRE. Any tool which
+ * uses the  JRE must peform this step to ensure the complete synthesis.
+ * The EnsureJreInstallation function calls preJVMStart based on
+ * the conditions outlined below, noting that the operation
+ * will fail silently if any of conditions are not met.
+ * NOTE: this call must be made before jvm.dll is loaded, or jvm.cfg
+ * is read, since jvm.cfg will be modified by the preJVMStart.
+ * 1. Are we on a supported platform.
+ * 2. Find the location of the JRE or the Kernel JRE.
+ * 3. check existence of JREHOME/lib/bundles
+ * 4. check jkernel.dll and invoke the entry-point
+ */
+typedef VOID (WINAPI *PREJVMSTART)();
+
+static void
+EnsureJreInstallation(const char* jrepath)
+{
+    HINSTANCE handle;
+    char tmpbuf[MAXPATHLEN];
+    PREJVMSTART PreJVMStart;
+    struct stat s;
+
+    /* 32 bit windows only please */
+    if (strcmp(GetArch(), "i386") != 0 ) {
+        if (_launcher_debug) {
+            printf("EnsureJreInstallation:unsupported platform\n");
+        }
+        return;
+    }
+    /* Does our bundle directory exist ? */
+    strcpy(tmpbuf, jrepath);
+    strcat(tmpbuf, "\\lib\\bundles");
+    if (stat(tmpbuf, &s) != 0) {
+        if (_launcher_debug) {
+            printf("EnsureJreInstallation:<%s>:not found\n", tmpbuf);
+        }
+        return;
+    }
+    /* Does our jkernel dll exist ? */
+    strcpy(tmpbuf, jrepath);
+    strcat(tmpbuf, "\\bin\\jkernel.dll");
+    if (stat(tmpbuf, &s) != 0) {
+        if (_launcher_debug) {
+            printf("EnsureJreInstallation:<%s>:not found\n", tmpbuf);
+        }
+        return;
+    }
+    /* The Microsoft C Runtime Library needs to be loaded first. */
+    if (!LoadMSVCRT()) {
+        if (_launcher_debug) {
+            printf("EnsureJreInstallation:could not load C runtime DLL\n");
+        }
+        return;
+    }
+    /* Load the jkernel.dll */
+    if ((handle = LoadLibrary(tmpbuf)) == 0) {
+        if (_launcher_debug) {
+            printf("EnsureJreInstallation:%s:load failed\n", tmpbuf);
+        }
+        return;
+    }
+    /* Get the function address */
+    PreJVMStart = (PREJVMSTART)GetProcAddress(handle, "preJVMStart");
+    if (PreJVMStart == NULL) {
+        if (_launcher_debug) {
+            printf("EnsureJreInstallation:preJVMStart:function lookup failed\n");
+        }
+        FreeLibrary(handle);
+        return;
+    }
+    PreJVMStart();
+    if (_launcher_debug) {
+        printf("EnsureJreInstallation:preJVMStart:called\n");
+    }
+    FreeLibrary(handle);
+    return;
+}
+
+/*
+ * Find path to JRE based on .exe's location or registry settings.
+ */
+jboolean
+GetJREPath(char *path, jint pathsize)
+{
+    char javadll[MAXPATHLEN];
+    struct stat s;
+
+    if (GetApplicationHome(path, pathsize)) {
+        /* Is JRE co-located with the application? */
+        sprintf(javadll, "%s\\bin\\" JAVA_DLL, path);
+        if (stat(javadll, &s) == 0) {
+            goto found;
+        }
+
+        /* Does this app ship a private JRE in <apphome>\jre directory? */
+        sprintf(javadll, "%s\\jre\\bin\\" JAVA_DLL, path);
+        if (stat(javadll, &s) == 0) {
+            strcat(path, "\\jre");
+            goto found;
+        }
+    }
+
+#ifndef GAMMA
+    /* Look for a public JRE on this machine. */
+    if (GetPublicJREHome(path, pathsize)) {
+        goto found;
+    }
+#endif
+
+    fprintf(stderr, "Error: could not find " JAVA_DLL "\n");
+    return JNI_FALSE;
+
+ found:
+    if (_launcher_debug)
+      printf("JRE path is %s\n", path);
+    return JNI_TRUE;
+}
+
+/*
+ * Given a JRE location and a JVM type, construct what the name the
+ * JVM shared library will be.  Return true, if such a library
+ * exists, false otherwise.
+ */
+static jboolean
+GetJVMPath(const char *jrepath, const char *jvmtype,
+           char *jvmpath, jint jvmpathsize)
+{
+    struct stat s;
+
+#ifndef GAMMA
+    if (strchr(jvmtype, '/') || strchr(jvmtype, '\\')) {
+        sprintf(jvmpath, "%s\\" JVM_DLL, jvmtype);
+    } else {
+        sprintf(jvmpath, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype);
+    }
+#else
+    /*
+     * For gamma launcher, JVM is either built-in or in the same directory.
+     * Either way we return "<exe_path>/jvm.dll" where <exe_path> is the
+     * directory where gamma launcher is located.
+     */
+
+    char *p;
+    GetModuleFileName(0, jvmpath, jvmpathsize);
+
+    p = strrchr(jvmpath, '\\');
+    if (p) {
+       /* replace executable name with libjvm.so */
+       snprintf(p + 1, jvmpathsize - (p + 1 - jvmpath), "%s", JVM_DLL);
+    } else {
+       /* this case shouldn't happen */
+       snprintf(jvmpath, jvmpathsize, "%s", JVM_DLL);
+    }
+#endif /* ifndef GAMMA */
+
+    if (stat(jvmpath, &s) == 0) {
+        return JNI_TRUE;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
+/*
+ * Load a jvm from "jvmpath" and initialize the invocation functions.
+ */
+jboolean
+LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
+{
+#ifdef GAMMA
+    /* JVM is directly linked with gamma launcher; no Loadlibrary() */
+    ifn->CreateJavaVM = JNI_CreateJavaVM;
+    ifn->GetDefaultJavaVMInitArgs = JNI_GetDefaultJavaVMInitArgs;
+    return JNI_TRUE;
+#else
+    HINSTANCE handle;
+
+    if (_launcher_debug) {
+        printf("JVM path is %s\n", jvmpath);
+    }
+
+    /* The Microsoft C Runtime Library needs to be loaded first. */
+    LoadMSVCRT();
+
+    /* Load the Java VM DLL */
+    if ((handle = LoadLibrary(jvmpath)) == 0) {
+        ReportErrorMessage2("Error loading: %s", (char *)jvmpath, JNI_TRUE);
+        return JNI_FALSE;
+    }
+
+    /* Now get the function addresses */
+    ifn->CreateJavaVM =
+        (void *)GetProcAddress(handle, "JNI_CreateJavaVM");
+    ifn->GetDefaultJavaVMInitArgs =
+        (void *)GetProcAddress(handle, "JNI_GetDefaultJavaVMInitArgs");
+    if (ifn->CreateJavaVM == 0 || ifn->GetDefaultJavaVMInitArgs == 0) {
+        ReportErrorMessage2("Error: can't find JNI interfaces in: %s",
+                            (char *)jvmpath, JNI_TRUE);
+        return JNI_FALSE;
+    }
+
+    return JNI_TRUE;
+#endif /* ifndef GAMMA */
+}
+
+/*
+ * If app is "c:\foo\bin\javac", then put "c:\foo" into buf.
+ */
+jboolean
+GetApplicationHome(char *buf, jint bufsize)
+{
+#ifndef GAMMA
+    char *cp;
+    GetModuleFileName(0, buf, bufsize);
+    *strrchr(buf, '\\') = '\0'; /* remove .exe file name */
+    if ((cp = strrchr(buf, '\\')) == 0) {
+        /* This happens if the application is in a drive root, and
+         * there is no bin directory. */
+        buf[0] = '\0';
+        return JNI_FALSE;
+    }
+    *cp = '\0';  /* remove the bin\ part */
+    return JNI_TRUE;
+
+#else /* ifndef GAMMA */
+
+    /* gamma launcher uses JAVA_HOME or ALT_JAVA_HOME environment variable to find JDK/JRE */
+    char* java_home_var = getenv("ALT_JAVA_HOME");
+    if (java_home_var == NULL) {
+       java_home_var = getenv("JAVA_HOME");
+    }
+    if (java_home_var == NULL) {
+       printf("JAVA_HOME or ALT_JAVA_HOME must point to a valid JDK/JRE to run gamma\n");
+       return JNI_FALSE;
+    }
+    snprintf(buf, bufsize, "%s", java_home_var);
+    return JNI_TRUE;
+#endif /* ifndef GAMMA */
+}
+
+#ifdef JAVAW
+__declspec(dllimport) char **__initenv;
+
+int WINAPI
+WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow)
+{
+    int   ret;
+
+    __initenv = _environ;
+    ret = main(__argc, __argv);
+
+    return ret;
+}
+#endif
+
+#ifndef GAMMA
+
+/*
+ * Helpers to look in the registry for a public JRE.
+ */
+                    /* Same for 1.5.0, 1.5.1, 1.5.2 etc. */
+#define DOTRELEASE  JDK_MAJOR_VERSION "." JDK_MINOR_VERSION
+#define JRE_KEY     "Software\\JavaSoft\\Java Runtime Environment"
+
+static jboolean
+GetStringFromRegistry(HKEY key, const char *name, char *buf, jint bufsize)
+{
+    DWORD type, size;
+
+    if (RegQueryValueEx(key, name, 0, &type, 0, &size) == 0
+        && type == REG_SZ
+        && (size < (unsigned int)bufsize)) {
+        if (RegQueryValueEx(key, name, 0, 0, buf, &size) == 0) {
+            return JNI_TRUE;
+        }
+    }
+    return JNI_FALSE;
+}
+
+static jboolean
+GetPublicJREHome(char *buf, jint bufsize)
+{
+    HKEY key, subkey;
+    char version[MAXPATHLEN];
+
+    /*
+     * Note: There is a very similar implementation of the following
+     * registry reading code in the Windows java control panel (javacp.cpl).
+     * If there are bugs here, a similar bug probably exists there.  Hence,
+     * changes here require inspection there.
+     */
+
+    /* Find the current version of the JRE */
+    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, JRE_KEY, 0, KEY_READ, &key) != 0) {
+        fprintf(stderr, "Error opening registry key '" JRE_KEY "'\n");
+        return JNI_FALSE;
+    }
+
+    if (!GetStringFromRegistry(key, "CurrentVersion",
+                               version, sizeof(version))) {
+        fprintf(stderr, "Failed reading value of registry key:\n\t"
+                JRE_KEY "\\CurrentVersion\n");
+        RegCloseKey(key);
+        return JNI_FALSE;
+    }
+
+    if (strcmp(version, DOTRELEASE) != 0) {
+        fprintf(stderr, "Registry key '" JRE_KEY "\\CurrentVersion'\nhas "
+                "value '%s', but '" DOTRELEASE "' is required.\n", version);
+        RegCloseKey(key);
+        return JNI_FALSE;
+    }
+
+    /* Find directory where the current version is installed. */
+    if (RegOpenKeyEx(key, version, 0, KEY_READ, &subkey) != 0) {
+        fprintf(stderr, "Error opening registry key '"
+                JRE_KEY "\\%s'\n", version);
+        RegCloseKey(key);
+        return JNI_FALSE;
+    }
+
+    if (!GetStringFromRegistry(subkey, "JavaHome", buf, bufsize)) {
+        fprintf(stderr, "Failed reading value of registry key:\n\t"
+                JRE_KEY "\\%s\\JavaHome\n", version);
+        RegCloseKey(key);
+        RegCloseKey(subkey);
+        return JNI_FALSE;
+    }
+
+    if (_launcher_debug) {
+        char micro[MAXPATHLEN];
+        if (!GetStringFromRegistry(subkey, "MicroVersion", micro,
+                                   sizeof(micro))) {
+            printf("Warning: Can't read MicroVersion\n");
+            micro[0] = '\0';
+        }
+        printf("Version major.minor.micro = %s.%s\n", version, micro);
+    }
+
+    RegCloseKey(key);
+    RegCloseKey(subkey);
+    return JNI_TRUE;
+}
+
+#endif /* ifndef GAMMA */
+
+/*
+ * Support for doing cheap, accurate interval timing.
+ */
+static jboolean counterAvailable = JNI_FALSE;
+static jboolean counterInitialized = JNI_FALSE;
+static LARGE_INTEGER counterFrequency;
+
+jlong CounterGet()
+{
+    LARGE_INTEGER count;
+
+    if (!counterInitialized) {
+        counterAvailable = QueryPerformanceFrequency(&counterFrequency);
+        counterInitialized = JNI_TRUE;
+    }
+    if (!counterAvailable) {
+        return 0;
+    }
+    QueryPerformanceCounter(&count);
+    return (jlong)(count.QuadPart);
+}
+
+jlong Counter2Micros(jlong counts)
+{
+    if (!counterAvailable || !counterInitialized) {
+        return 0;
+    }
+    return (counts * 1000 * 1000)/counterFrequency.QuadPart;
+}
+
+void ReportErrorMessage(char * message, jboolean always) {
+#ifdef JAVAW
+  if (message != NULL) {
+    MessageBox(NULL, message, "Java Virtual Machine Launcher",
+               (MB_OK|MB_ICONSTOP|MB_APPLMODAL));
+  }
+#else
+  if (always) {
+    fprintf(stderr, "%s\n", message);
+  }
+#endif
+}
+
+void ReportErrorMessage2(char * format, char * string, jboolean always) {
+  /*
+   * The format argument must be a printf format string with one %s
+   * argument, which is passed the string argument.
+   */
+#ifdef JAVAW
+  size_t size;
+  char * message;
+  size = strlen(format) + strlen(string);
+  message = (char*)JLI_MemAlloc(size*sizeof(char));
+  sprintf(message, (const char *)format, string);
+
+  if (message != NULL) {
+    MessageBox(NULL, message, "Java Virtual Machine Launcher",
+               (MB_OK|MB_ICONSTOP|MB_APPLMODAL));
+    JLI_MemFree(message);
+  }
+#else
+  if (always) {
+    fprintf(stderr, (const char *)format, string);
+    fprintf(stderr, "\n");
+  }
+#endif
+}
+
+/*
+ * As ReportErrorMessage2 (above) except the system message (if any)
+ * associated with this error is written to a second %s format specifier
+ * in the format argument.
+ */
+void ReportSysErrorMessage2(char * format, char * string, jboolean always) {
+  int   save_errno = errno;
+  DWORD errval;
+  int   freeit = 0;
+  char  *errtext = NULL;
+
+  if ((errval = GetLastError()) != 0) {         /* Platform SDK / DOS Error */
+    int n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|
+      FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_ALLOCATE_BUFFER,
+      NULL, errval, 0, (LPTSTR)&errtext, 0, NULL);
+    if (errtext == NULL || n == 0) {            /* Paranoia check */
+      errtext = "";
+      n = 0;
+    } else {
+      freeit = 1;
+      if (n > 2) {                              /* Drop final CR, LF */
+        if (errtext[n - 1] == '\n') n--;
+        if (errtext[n - 1] == '\r') n--;
+        errtext[n] = '\0';
+      }
+    }
+  } else        /* C runtime error that has no corresponding DOS error code */
+    errtext = strerror(save_errno);
+
+#ifdef JAVAW
+  {
+    size_t size;
+    char * message;
+    size = strlen(format) + strlen(string) + strlen(errtext);
+    message = (char*)JLI_MemAlloc(size*sizeof(char));
+    sprintf(message, (const char *)format, string, errtext);
+
+    if (message != NULL) {
+      MessageBox(NULL, message, "Java Virtual Machine Launcher",
+               (MB_OK|MB_ICONSTOP|MB_APPLMODAL));
+      JLI_MemFree(message);
+    }
+  }
+#else
+  if (always) {
+    fprintf(stderr, (const char *)format, string, errtext);
+    fprintf(stderr, "\n");
+  }
+#endif
+  if (freeit)
+    (void)LocalFree((HLOCAL)errtext);
+}
+
+void  ReportExceptionDescription(JNIEnv * env) {
+#ifdef JAVAW
+  /*
+   * This code should be replaced by code which opens a window with
+   * the exception detail message.
+   */
+  (*env)->ExceptionDescribe(env);
+#else
+  (*env)->ExceptionDescribe(env);
+#endif
+}
+
+
+/*
+ * Return JNI_TRUE for an option string that has no effect but should
+ * _not_ be passed on to the vm; return JNI_FALSE otherwise. On
+ * windows, there are no options that should be screened in this
+ * manner.
+ */
+jboolean RemovableMachineDependentOption(char * option) {
+#ifdef ENABLE_AWT_PRELOAD
+    if (awtPreloadD3D < 0) {
+        /* Tests the command line parameter only if not set yet. */
+        if (GetBoolParamValue(PARAM_PRELOAD_D3D, option) == 1) {
+            awtPreloadD3D = 1;
+        }
+    }
+    if (awtPreloadD3D != 0) {
+        /* Don't test the command line parameters if already disabled. */
+        if (GetBoolParamValue(PARAM_NODDRAW, option) == 1
+            || GetBoolParamValue(PARAM_D3D, option) == 0
+            || GetBoolParamValue(PARAM_OPENGL, option) == 1)
+        {
+            awtPreloadD3D = 0;
+        }
+    }
+#endif /* ENABLE_AWT_PRELOAD */
+
+    return JNI_FALSE;
+}
+
+void PrintMachineDependentOptions() {
+  return;
+}
+
+#ifndef GAMMA
+
+jboolean
+ServerClassMachine() {
+  jboolean result = JNI_FALSE;
+#if   defined(NEVER_ACT_AS_SERVER_CLASS_MACHINE)
+  result = JNI_FALSE;
+#elif defined(ALWAYS_ACT_AS_SERVER_CLASS_MACHINE)
+  result = JNI_TRUE;
+#endif
+  return result;
+}
+
+/*
+ * Determine if there is an acceptable JRE in the registry directory top_key.
+ * Upon locating the "best" one, return a fully qualified path to it.
+ * "Best" is defined as the most advanced JRE meeting the constraints
+ * contained in the manifest_info. If no JRE in this directory meets the
+ * constraints, return NULL.
+ *
+ * It doesn't matter if we get an error reading the registry, or we just
+ * don't find anything interesting in the directory.  We just return NULL
+ * in either case.
+ */
+static char *
+ProcessDir(manifest_info* info, HKEY top_key) {
+    DWORD   index = 0;
+    HKEY    ver_key;
+    char    name[MAXNAMELEN];
+    int     len;
+    char    *best = NULL;
+
+    /*
+     * Enumerate "<top_key>/SOFTWARE/JavaSoft/Java Runtime Environment"
+     * searching for the best available version.
+     */
+    while (RegEnumKey(top_key, index, name, MAXNAMELEN) == ERROR_SUCCESS) {
+        index++;
+        if (JLI_AcceptableRelease(name, info->jre_version))
+            if ((best == NULL) || (JLI_ExactVersionId(name, best) > 0)) {
+                if (best != NULL)
+                    JLI_MemFree(best);
+                best = JLI_StringDup(name);
+            }
+    }
+
+    /*
+     * Extract "JavaHome" from the "best" registry directory and return
+     * that path.  If no appropriate version was located, or there is an
+     * error in extracting the "JavaHome" string, return null.
+     */
+    if (best == NULL)
+        return (NULL);
+    else {
+        if (RegOpenKeyEx(top_key, best, 0, KEY_READ, &ver_key)
+          != ERROR_SUCCESS) {
+            JLI_MemFree(best);
+            if (ver_key != NULL)
+                RegCloseKey(ver_key);
+            return (NULL);
+        }
+        JLI_MemFree(best);
+        len = MAXNAMELEN;
+        if (RegQueryValueEx(ver_key, "JavaHome", NULL, NULL, (LPBYTE)name, &len)
+          != ERROR_SUCCESS) {
+            if (ver_key != NULL)
+                RegCloseKey(ver_key);
+            return (NULL);
+        }
+        if (ver_key != NULL)
+            RegCloseKey(ver_key);
+        return (JLI_StringDup(name));
+    }
+}
+
+/*
+ * This is the global entry point. It examines the host for the optimal
+ * JRE to be used by scanning a set of registry entries.  This set of entries
+ * is hardwired on Windows as "Software\JavaSoft\Java Runtime Environment"
+ * under the set of roots "{ HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }".
+ *
+ * This routine simply opens each of these registry directories before passing
+ * control onto ProcessDir().
+ */
+char *
+LocateJRE(manifest_info* info) {
+    HKEY    key = NULL;
+    char    *path;
+    int     key_index;
+    HKEY    root_keys[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
+
+    for (key_index = 0; key_index <= 1; key_index++) {
+        if (RegOpenKeyEx(root_keys[key_index], JRE_KEY, 0, KEY_READ, &key)
+          == ERROR_SUCCESS)
+            if ((path = ProcessDir(info, key)) != NULL) {
+                if (key != NULL)
+                    RegCloseKey(key);
+                return (path);
+            }
+        if (key != NULL)
+            RegCloseKey(key);
+    }
+    return NULL;
+}
+
+
+/*
+ * Local helper routine to isolate a single token (option or argument)
+ * from the command line.
+ *
+ * This routine accepts a pointer to a character pointer.  The first
+ * token (as defined by MSDN command-line argument syntax) is isolated
+ * from that string.
+ *
+ * Upon return, the input character pointer pointed to by the parameter s
+ * is updated to point to the remainding, unscanned, portion of the string,
+ * or to a null character if the entire string has been consummed.
+ *
+ * This function returns a pointer to a null-terminated string which
+ * contains the isolated first token, or to the null character if no
+ * token could be isolated.
+ *
+ * Note the side effect of modifying the input string s by the insertion
+ * of a null character, making it two strings.
+ *
+ * See "Parsing C Command-Line Arguments" in the MSDN Library for the
+ * parsing rule details.  The rule summary from that specification is:
+ *
+ *  * Arguments are delimited by white space, which is either a space or a tab.
+ *
+ *  * A string surrounded by double quotation marks is interpreted as a single
+ *    argument, regardless of white space contained within. A quoted string can
+ *    be embedded in an argument. Note that the caret (^) is not recognized as
+ *    an escape character or delimiter.
+ *
+ *  * A double quotation mark preceded by a backslash, \", is interpreted as a
+ *    literal double quotation mark (").
+ *
+ *  * Backslashes are interpreted literally, unless they immediately precede a
+ *    double quotation mark.
+ *
+ *  * If an even number of backslashes is followed by a double quotation mark,
+ *    then one backslash (\) is placed in the argv array for every pair of
+ *    backslashes (\\), and the double quotation mark (") is interpreted as a
+ *    string delimiter.
+ *
+ *  * If an odd number of backslashes is followed by a double quotation mark,
+ *    then one backslash (\) is placed in the argv array for every pair of
+ *    backslashes (\\) and the double quotation mark is interpreted as an
+ *    escape sequence by the remaining backslash, causing a literal double
+ *    quotation mark (") to be placed in argv.
+ */
+static char*
+nextarg(char** s) {
+    char    *p = *s;
+    char    *head;
+    int     slashes = 0;
+    int     inquote = 0;
+
+    /*
+     * Strip leading whitespace, which MSDN defines as only space or tab.
+     * (Hence, no locale specific "isspace" here.)
+     */
+    while (*p != (char)0 && (*p == ' ' || *p == '\t'))
+        p++;
+    head = p;                   /* Save the start of the token to return */
+
+    /*
+     * Isolate a token from the command line.
+     */
+    while (*p != (char)0 && (inquote || !(*p == ' ' || *p == '\t'))) {
+        if (*p == '\\' && *(p+1) == '"' && slashes % 2 == 0)
+            p++;
+        else if (*p == '"')
+            inquote = !inquote;
+        slashes = (*p++ == '\\') ? slashes + 1 : 0;
+    }
+
+    /*
+     * If the token isolated isn't already terminated in a "char zero",
+     * then replace the whitespace character with one and move to the
+     * next character.
+     */
+    if (*p != (char)0)
+        *p++ = (char)0;
+
+    /*
+     * Update the parameter to point to the head of the remaining string
+     * reflecting the command line and return a pointer to the leading
+     * token which was isolated from the command line.
+     */
+    *s = p;
+    return (head);
+}
+
+/*
+ * Local helper routine to return a string equivalent to the input string
+ * s, but with quotes removed so the result is a string as would be found
+ * in argv[].  The returned string should be freed by a call to JLI_MemFree().
+ *
+ * The rules for quoting (and escaped quotes) are:
+ *
+ *  1 A double quotation mark preceded by a backslash, \", is interpreted as a
+ *    literal double quotation mark (").
+ *
+ *  2 Backslashes are interpreted literally, unless they immediately precede a
+ *    double quotation mark.
+ *
+ *  3 If an even number of backslashes is followed by a double quotation mark,
+ *    then one backslash (\) is placed in the argv array for every pair of
+ *    backslashes (\\), and the double quotation mark (") is interpreted as a
+ *    string delimiter.
+ *
+ *  4 If an odd number of backslashes is followed by a double quotation mark,
+ *    then one backslash (\) is placed in the argv array for every pair of
+ *    backslashes (\\) and the double quotation mark is interpreted as an
+ *    escape sequence by the remaining backslash, causing a literal double
+ *    quotation mark (") to be placed in argv.
+ */
+static char*
+unquote(const char *s) {
+    const char *p = s;          /* Pointer to the tail of the original string */
+    char *un = (char*)JLI_MemAlloc(strlen(s) + 1);  /* Ptr to unquoted string */
+    char *pun = un;             /* Pointer to the tail of the unquoted string */
+
+    while (*p != '\0') {
+        if (*p == '"') {
+            p++;
+        } else if (*p == '\\') {
+            const char *q = p + strspn(p,"\\");
+            if (*q == '"')
+                do {
+                    *pun++ = '\\';
+                    p += 2;
+                 } while (*p == '\\' && p < q);
+            else
+                while (p < q)
+                    *pun++ = *p++;
+        } else {
+            *pun++ = *p++;
+        }
+    }
+    *pun = '\0';
+    return un;
+}
+
+/*
+ * Given a path to a jre to execute, this routine checks if this process
+ * is indeed that jre.  If not, it exec's that jre.
+ *
+ * We want to actually check the paths rather than just the version string
+ * built into the executable, so that given version specification will yield
+ * the exact same Java environment, regardless of the version of the arbitrary
+ * launcher we start with.
+ */
+void
+ExecJRE(char *jre, char **argv) {
+    int     len;
+    char    *progname;
+    char    path[MAXPATHLEN + 1];
+
+    /*
+     * Determine the executable we are building (or in the rare case, running).
+     */
+#ifdef JAVA_ARGS  /* javac, jar and friends. */
+    progname = "java";
+#else             /* java, oldjava, javaw and friends */
+#ifdef PROGNAME
+    progname = PROGNAME;
+#else
+    {
+        char *s;
+        progname = *argv;
+        if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) {
+            progname = s + 1;
+        }
+    }
+#endif /* PROGNAME */
+#endif /* JAVA_ARGS */
+
+    /*
+     * Resolve the real path to the currently running launcher.
+     */
+    len = GetModuleFileName(NULL, path, MAXPATHLEN + 1);
+    if (len == 0 || len > MAXPATHLEN) {
+        ReportSysErrorMessage2(
+          "Unable to resolve path to current %s executable: %s",
+          progname, JNI_TRUE);
+        exit(1);
+    }
+
+    if (_launcher_debug) {
+        printf("ExecJRE: old: %s\n", path);
+        printf("ExecJRE: new: %s\n", jre);
+    }
+
+    /*
+     * If the path to the selected JRE directory is a match to the initial
+     * portion of the path to the currently executing JRE, we have a winner!
+     * If so, just return. (strnicmp() is the Windows equiv. of strncasecmp().)
+     */
+    if (strnicmp(jre, path, strlen(jre)) == 0)
+        return;                 /* I am the droid you were looking for */
+
+    /*
+     * If this isn't the selected version, exec the selected version.
+     */
+    (void)strcat(strcat(strcpy(path, jre), "\\bin\\"), progname);
+    (void)strcat(path, ".exe");
+
+    /*
+     * Although Windows has an execv() entrypoint, it doesn't actually
+     * overlay a process: it can only create a new process and terminate
+     * the old process.  Therefore, any processes waiting on the initial
+     * process wake up and they shouldn't.  Hence, a chain of pseudo-zombie
+     * processes must be retained to maintain the proper wait semantics.
+     * Fortunately the image size of the launcher isn't too large at this
+     * time.
+     *
+     * If it weren't for this semantic flaw, the code below would be ...
+     *
+     *     execv(path, argv);
+     *     ReportErrorMessage2("Exec of %s failed\n", path, JNI_TRUE);
+     *     exit(1);
+     *
+     * The incorrect exec semantics could be addressed by:
+     *
+     *     exit((int)spawnv(_P_WAIT, path, argv));
+     *
+     * Unfortunately, a bug in Windows spawn/exec impementation prevents
+     * this from completely working.  All the Windows POSIX process creation
+     * interfaces are implemented as wrappers around the native Windows
+     * function CreateProcess().  CreateProcess() takes a single string
+     * to specify command line options and arguments, so the POSIX routine
+     * wrappers build a single string from the argv[] array and in the
+     * process, any quoting information is lost.
+     *
+     * The solution to this to get the original command line, to process it
+     * to remove the new multiple JRE options (if any) as was done for argv
+     * in the common SelectVersion() routine and finally to pass it directly
+     * to the native CreateProcess() Windows process control interface.
+     */
+    {
+        char    *cmdline;
+        char    *p;
+        char    *np;
+        char    *ocl;
+        char    *ccl;
+        char    *unquoted;
+        DWORD   exitCode;
+        STARTUPINFO si;
+        PROCESS_INFORMATION pi;
+
+        /*
+         * The following code block gets and processes the original command
+         * line, replacing the argv[0] equivalent in the command line with
+         * the path to the new executable and removing the appropriate
+         * Multiple JRE support options. Note that similar logic exists
+         * in the platform independent SelectVersion routine, but is
+         * replicated here due to the syntax of CreateProcess().
+         *
+         * The magic "+ 4" characters added to the command line length are
+         * 2 possible quotes around the path (argv[0]), a space after the
+         * path and a terminating null character.
+         */
+        ocl = GetCommandLine();
+        np = ccl = JLI_StringDup(ocl);
+        p = nextarg(&np);               /* Discard argv[0] */
+        cmdline = (char *)JLI_MemAlloc(strlen(path) + strlen(np) + 4);
+        if (strchr(path, (int)' ') == NULL && strchr(path, (int)'\t') == NULL)
+            cmdline = strcpy(cmdline, path);
+        else
+            cmdline = strcat(strcat(strcpy(cmdline, "\""), path), "\"");
+
+        while (*np != (char)0) {                /* While more command-line */
+            p = nextarg(&np);
+            if (*p != (char)0) {                /* If a token was isolated */
+                unquoted = unquote(p);
+                if (*unquoted == '-') {         /* Looks like an option */
+                    if (strcmp(unquoted, "-classpath") == 0 ||
+                      strcmp(unquoted, "-cp") == 0) {   /* Unique cp syntax */
+                        cmdline = strcat(strcat(cmdline, " "), p);
+                        p = nextarg(&np);
+                        if (*p != (char)0)      /* If a token was isolated */
+                            cmdline = strcat(strcat(cmdline, " "), p);
+                    } else if (strncmp(unquoted, "-version:", 9) != 0 &&
+                      strcmp(unquoted, "-jre-restrict-search") != 0 &&
+                      strcmp(unquoted, "-no-jre-restrict-search") != 0) {
+                        cmdline = strcat(strcat(cmdline, " "), p);
+                    }
+                } else {                        /* End of options */
+                    cmdline = strcat(strcat(cmdline, " "), p);
+                    cmdline = strcat(strcat(cmdline, " "), np);
+                    JLI_MemFree((void *)unquoted);
+                    break;
+                }
+                JLI_MemFree((void *)unquoted);
+            }
+        }
+        JLI_MemFree((void *)ccl);
+
+        if (_launcher_debug) {
+            np = ccl = JLI_StringDup(cmdline);
+            p = nextarg(&np);
+            printf("ReExec Command: %s (%s)\n", path, p);
+            printf("ReExec Args: %s\n", np);
+            JLI_MemFree((void *)ccl);
+        }
+        (void)fflush(stdout);
+        (void)fflush(stderr);
+
+        /*
+         * The following code is modeled after a model presented in the
+         * Microsoft Technical Article "Moving Unix Applications to
+         * Windows NT" (March 6, 1994) and "Creating Processes" on MSDN
+         * (Februrary 2005).  It approximates UNIX spawn semantics with
+         * the parent waiting for termination of the child.
+         */
+        memset(&si, 0, sizeof(si));
+        si.cb =sizeof(STARTUPINFO);
+        memset(&pi, 0, sizeof(pi));
+
+        if (!CreateProcess((LPCTSTR)path,       /* executable name */
+          (LPTSTR)cmdline,                      /* command line */
+          (LPSECURITY_ATTRIBUTES)NULL,          /* process security attr. */
+          (LPSECURITY_ATTRIBUTES)NULL,          /* thread security attr. */
+          (BOOL)TRUE,                           /* inherits system handles */
+          (DWORD)0,                             /* creation flags */
+          (LPVOID)NULL,                         /* environment block */
+          (LPCTSTR)NULL,                        /* current directory */
+          (LPSTARTUPINFO)&si,                   /* (in) startup information */
+          (LPPROCESS_INFORMATION)&pi)) {        /* (out) process information */
+            ReportSysErrorMessage2("CreateProcess(%s, ...) failed: %s",
+              path, JNI_TRUE);
+              exit(1);
+        }
+
+        if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED) {
+            if (GetExitCodeProcess(pi.hProcess, &exitCode) == FALSE)
+                exitCode = 1;
+        } else {
+            ReportErrorMessage("WaitForSingleObject() failed.", JNI_TRUE);
+            exitCode = 1;
+        }
+
+        CloseHandle(pi.hThread);
+        CloseHandle(pi.hProcess);
+
+        exit(exitCode);
+    }
+
+}
+
+#endif /* ifndef GAMMA */
+
+
+/*
+ * Wrapper for platform dependent unsetenv function.
+ */
+int
+UnsetEnv(char *name)
+{
+    int ret;
+    char *buf = JLI_MemAlloc(strlen(name) + 2);
+    buf = strcat(strcpy(buf, name), "=");
+    ret = _putenv(buf);
+    JLI_MemFree(buf);
+    return (ret);
+}
+
+/* --- Splash Screen shared library support --- */
+
+static const char* SPLASHSCREEN_SO = "\\bin\\splashscreen.dll";
+
+static HMODULE hSplashLib = NULL;
+
+void* SplashProcAddress(const char* name) {
+    char libraryPath[MAXPATHLEN]; /* some extra space for strcat'ing SPLASHSCREEN_SO */
+
+    if (!GetJREPath(libraryPath, MAXPATHLEN)) {
+        return NULL;
+    }
+    if (strlen(libraryPath)+strlen(SPLASHSCREEN_SO) >= MAXPATHLEN) {
+        return NULL;
+    }
+    strcat(libraryPath, SPLASHSCREEN_SO);
+
+    if (!hSplashLib) {
+        hSplashLib = LoadLibrary(libraryPath);
+    }
+    if (hSplashLib) {
+        return GetProcAddress(hSplashLib, name);
+    } else {
+        return NULL;
+    }
+}
+
+void SplashFreeLibrary() {
+    if (hSplashLib) {
+        FreeLibrary(hSplashLib);
+        hSplashLib = NULL;
+    }
+}
+
+const char *
+jlong_format_specifier() {
+    return "%I64d";
+}
+
+/*
+ * Block current thread and continue execution in a new thread
+ */
+int
+ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void * args) {
+    int rslt = 0;
+    unsigned thread_id;
+
+#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
+#define STACK_SIZE_PARAM_IS_A_RESERVATION  (0x10000)
+#endif
+
+    /*
+     * STACK_SIZE_PARAM_IS_A_RESERVATION is what we want, but it's not
+     * supported on older version of Windows. Try first with the flag; and
+     * if that fails try again without the flag. See MSDN document or HotSpot
+     * source (os_win32.cpp) for details.
+     */
+    HANDLE thread_handle =
+      (HANDLE)_beginthreadex(NULL,
+                             (unsigned)stack_size,
+                             continuation,
+                             args,
+                             STACK_SIZE_PARAM_IS_A_RESERVATION,
+                             &thread_id);
+    if (thread_handle == NULL) {
+      thread_handle =
+      (HANDLE)_beginthreadex(NULL,
+                             (unsigned)stack_size,
+                             continuation,
+                             args,
+                             0,
+                             &thread_id);
+    }
+
+    /* AWT preloading (AFTER main thread start) */
+#ifdef ENABLE_AWT_PRELOAD
+    /* D3D preloading */
+    if (awtPreloadD3D != 0) {
+        char *envValue;
+        /* D3D routines checks env.var J2D_D3D if no appropriate
+         * command line params was specified
+         */
+        envValue = getenv("J2D_D3D");
+        if (envValue != NULL && stricmp(envValue, "false") == 0) {
+            awtPreloadD3D = 0;
+        }
+        /* Test that AWT preloading isn't disabled by J2D_D3D_PRELOAD env.var */
+        envValue = getenv("J2D_D3D_PRELOAD");
+        if (envValue != NULL && stricmp(envValue, "false") == 0) {
+            awtPreloadD3D = 0;
+        }
+        if (awtPreloadD3D < 0) {
+            /* If awtPreloadD3D is still undefined (-1), test
+             * if it is turned on by J2D_D3D_PRELOAD env.var.
+             * By default it's turned OFF.
+             */
+            awtPreloadD3D = 0;
+            if (envValue != NULL && stricmp(envValue, "true") == 0) {
+                awtPreloadD3D = 1;
+            }
+        }
+    }
+    if (awtPreloadD3D) {
+        AWTPreload(D3D_PRELOAD_FUNC);
+    }
+#endif /* ENABLE_AWT_PRELOAD */
+
+    if (thread_handle) {
+      WaitForSingleObject(thread_handle, INFINITE);
+      GetExitCodeThread(thread_handle, &rslt);
+      CloseHandle(thread_handle);
+    } else {
+      rslt = continuation(args);
+    }
+
+#ifdef ENABLE_AWT_PRELOAD
+    if (awtPreloaded) {
+        AWTPreloadStop();
+    }
+#endif /* ENABLE_AWT_PRELOAD */
+
+    return rslt;
+}
+
+/* Linux only, empty on windows. */
+void SetJavaLauncherPlatformProps() {}
+
+
+//==============================
+// AWT preloading
+#ifdef ENABLE_AWT_PRELOAD
+
+typedef int FnPreloadStart(void);
+typedef void FnPreloadStop(void);
+static FnPreloadStop *fnPreloadStop = NULL;
+static HMODULE hPreloadAwt = NULL;
+
+/*
+ * Starts AWT preloading
+ */
+int AWTPreload(const char *funcName)
+{
+    int result = -1;
+
+    // load AWT library once (if several preload function should be called)
+    if (hPreloadAwt == NULL) {
+        // awt.dll is not loaded yet
+        char libraryPath[MAXPATHLEN];
+        int jrePathLen = 0;
+        HMODULE hJava = NULL;
+        HMODULE hVerify = NULL;
+
+        while (1) {
+            // awt.dll depends on jvm.dll & java.dll;
+            // jvm.dll is already loaded, so we need only java.dll;
+            // java.dll depends on MSVCRT lib & verify.dll.
+            if (!GetJREPath(libraryPath, MAXPATHLEN)) {
+                break;
+            }
+
+            // save path length
+            jrePathLen = strlen(libraryPath);
+
+            // load msvcrt 1st
+            LoadMSVCRT();
+
+            // load verify.dll
+            strcat(libraryPath, "\\bin\\verify.dll");
+            hVerify = LoadLibrary(libraryPath);
+            if (hVerify == NULL) {
+                break;
+            }
+
+            // restore jrePath
+            libraryPath[jrePathLen] = 0;
+            // load java.dll
+            strcat(libraryPath, "\\bin\\" JAVA_DLL);
+            hJava = LoadLibrary(libraryPath);
+            if (hJava == NULL) {
+                break;
+            }
+
+            // restore jrePath
+            libraryPath[jrePathLen] = 0;
+            // load awt.dll
+            strcat(libraryPath, "\\bin\\awt.dll");
+            hPreloadAwt = LoadLibrary(libraryPath);
+            if (hPreloadAwt == NULL) {
+                break;
+            }
+
+            // get "preloadStop" func ptr
+            fnPreloadStop = (FnPreloadStop *)GetProcAddress(hPreloadAwt, "preloadStop");
+
+            break;
+        }
+    }
+
+    if (hPreloadAwt != NULL) {
+        FnPreloadStart *fnInit = (FnPreloadStart *)GetProcAddress(hPreloadAwt, funcName);
+        if (fnInit != NULL) {
+            // don't forget to stop preloading
+            awtPreloaded = 1;
+
+            result = fnInit();
+        }
+    }
+
+    return result;
+}
+
+/*
+ * Terminates AWT preloading
+ */
+void AWTPreloadStop() {
+    if (fnPreloadStop != NULL) {
+        fnPreloadStop();
+    }
+}
+
+#endif /* ENABLE_AWT_PRELOAD */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/os/windows/launcher/java_md.h	Thu Dec 02 05:45:54 2010 -0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef JAVA_MD_H
+#define JAVA_MD_H
+
+#include <jni.h>
+#include <windows.h>
+#include <io.h>
+#ifndef GAMMA
+#include "manifest_info.h"
+#endif
+#include "jli_util.h"
+
+#ifdef GAMMA
+#define stricmp _stricmp
+#define strnicmp _strnicmp
+#define snprintf _snprintf
+#define strdup _strdup
+#endif
+
+#define PATH_SEPARATOR  ';'
+#define FILESEP         "\\"
+#define FILE_SEPARATOR  '\\'
+#define IS_FILE_SEPARATOR(c) ((c) == '\\' || (c) == '/')
+#define MAXPATHLEN      MAX_PATH
+#define MAXNAMELEN      MAX_PATH
+
+#ifdef JAVA_ARGS
+/*
+ * ApplicationHome is prepended to each of these entries; the resulting
+ * strings are concatenated (separated by PATH_SEPARATOR) and used as the
+ * value of -cp option to the launcher.
+ */
+#ifndef APP_CLASSPATH
+#define APP_CLASSPATH        { "\\lib\\tools.jar", "\\classes" }
+#endif
+#endif
+
+/*
+ * Support for doing cheap, accurate interval timing.
+ */
+extern jlong CounterGet(void);
+extern jlong Counter2Micros(jlong counts);
+
+#ifdef JAVAW
+#define main _main
+extern int _main(int argc, char **argv);
+#endif
+
+/*
+ * Function prototypes.
+ */
+#ifndef GAMMA
+char *LocateJRE(manifest_info *info);
+void ExecJRE(char *jre, char **argv);
+#endif
+int UnsetEnv(char *name);
+
+#endif
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Thu Dec 02 20:01:47 2010 +0100
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Thu Dec 02 05:45:54 2010 -0800
@@ -1708,7 +1708,37 @@
     return;
   }
 
+  buf[0] = '\0';
+  if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) {
+     // Support for the gamma launcher. Check for an
+     // ALT_JAVA_HOME or JAVA_HOME environment variable
+     // and fix up the path so it looks like
+     // libjvm.so is installed there (append a fake suffix
+     // hotspot/libjvm.so).
+     char* java_home_var = ::getenv("ALT_JAVA_HOME");
+     if (java_home_var == NULL) {
+        java_home_var = ::getenv("JAVA_HOME");
+     }
+     if (java_home_var != NULL && java_home_var[0] != 0) {
+
+        strncpy(buf, java_home_var, buflen);
+
+        // determine if this is a legacy image or modules image
+        // modules image doesn't have "jre" subdirectory
+        size_t len = strlen(buf);
+        char* jrebin_p = buf + len;
+        jio_snprintf(jrebin_p, buflen-len, "\\jre\\bin\\");
+        if (0 != _access(buf, 0)) {
+          jio_snprintf(jrebin_p, buflen-len, "\\bin\\");
+        }
+        len = strlen(buf);
+        jio_snprintf(buf + len, buflen-len, "hotspot\\jvm.dll");
+     }
+  }
+
+  if(buf[0] == '\0') {
   GetModuleFileName(vm_lib_handle, buf, buflen);
+  }
   strcpy(saved_jvm_path, buf);
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/launcher/java.c	Thu Dec 02 05:45:54 2010 -0800
@@ -0,0 +1,2078 @@
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * Gamma (Hotspot internal engineering test) launcher based on 6.0u22 JDK,
+ * search "GAMMA" for gamma specific changes.
+ *
+ * GAMMA: gamma launcher is much simpler than regular java launcher in that
+ *        JVM is either statically linked in or it is installed in the
+ *        same directory where the launcher exists, so we don't have to
+ *        worry about choosing the right JVM based on command line flag, jar
+ *        file and/or ergonomics. Intead of removing unused logic from source
+ *        they are commented out with #ifndef GAMMA, hopefully it'll be easier
+ *        to maintain this file in sync with regular JDK launcher.
+ */
+
+/*
+ * Shared source for 'java' command line tool.
+ *
+ * If JAVA_ARGS is defined, then acts as a launcher for applications. For
+ * instance, the JDK command line tools such as javac and javadoc (see
+ * makefiles for more details) are built with this program.  Any arguments
+ * prefixed with '-J' will be passed directly to the 'java' command.
+ */
+
+#ifdef GAMMA
+#  ifdef JAVA_ARGS
+#    error Do NOT define JAVA_ARGS when building gamma launcher
+#  endif
+#  if !defined(LINK_INTO_AOUT) && !defined(LINK_INTO_LIBJVM)
+#    error Either LINK_INTO_AOUT or LINK_INTO_LIBJVM must be defined
+#  endif
+#endif
+
+/*
+ * One job of the launcher is to remove command line options which the
+ * vm does not understand and will not process.  These options include
+ * options which select which style of vm is run (e.g. -client and
+ * -server) as well as options which select the data model to use.
+ * Additionally, for tools which invoke an underlying vm "-J-foo"
+ * options are turned into "-foo" options to the vm.  This option
+ * filtering is handled in a number of places in the launcher, some of
+ * it in machine-dependent code.  In this file, the function
+ * CheckJVMType removes vm style options and TranslateApplicationArgs
+ * removes "-J" prefixes.  On unix platforms, the
+ * CreateExecutionEnvironment function from the unix java_md.c file
+ * processes and removes -d<n> options.  However, in case
+ * CreateExecutionEnvironment does not need to exec because
+ * LD_LIBRARY_PATH is set acceptably and the data model does not need
+ * to be changed, ParseArguments will screen out the redundant -d<n>
+ * options and prevent them from being passed to the vm; this is done
+ * by using the machine-dependent call
+ * RemovableMachineDependentOption.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <jni.h>
+#include <jvm.h>
+#include "java.h"
+#ifndef GAMMA
+#include "manifest_info.h"
+#include "version_comp.h"
+#include "splashscreen.h"
+#endif
+#include "wildcard.h"
+
+#ifndef FULL_VERSION
+#define FULL_VERSION JDK_MAJOR_VERSION "." JDK_MINOR_VERSION
+#endif
+
+/*
+ * The following environment variable is used to influence the behavior
+ * 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
+ * to take precedence.
+ *
+ * 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
+ * interfaces.
+ */
+#define ENV_ENTRY "_JAVA_VERSION_SET"
+
+#ifndef GAMMA
+#define SPLASH_FILE_ENV_ENTRY "_JAVA_SPLASH_FILE"
+#define SPLASH_JAR_ENV_ENTRY "_JAVA_SPLASH_JAR"
+#endif
+
+static jboolean printVersion = JNI_FALSE; /* print and exit */
+static jboolean showVersion = JNI_FALSE;  /* print but continue */
+static char *progname;
+jboolean _launcher_debug = JNI_FALSE;
+
+#ifndef GAMMA
+/*
+ * 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.
+ */
+static char* splash_file_entry = NULL;
+static char* splash_jar_entry = NULL;
+#endif
+
+/*
+ * List of VM options to be specified when the VM is created.
+ */
+static JavaVMOption *options;
+static int numOptions, maxOptions;
+
+/*
+ * Prototypes for functions internal to launcher.
+ */
+static void SetClassPath(const char *s);
+static void SelectVersion(int argc, char **argv, char **main_class);
+static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile,
+                               char **pclassname, int *pret, const char *jvmpath);
+static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
+                              InvocationFunctions *ifn);
+static jstring NewPlatformString(JNIEnv *env, char *s);
+static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc);
+static jclass LoadClass(JNIEnv *env, char *name);
+static jstring GetMainClassName(JNIEnv *env, char *jarname);
+static void SetJavaCommandLineProp(char* classname, char* jarfile, int argc, char** argv);
+static void SetJavaLauncherProp(void);
+
+#ifdef JAVA_ARGS
+static void TranslateApplicationArgs(int *pargc, char ***pargv);
+static jboolean AddApplicationOptions(void);
+#endif
+
+static void PrintJavaVersion(JNIEnv *env);
+static void PrintUsage(void);
+static jint PrintXUsage(const char *jvmpath);
+
+static void SetPaths(int argc, char **argv);
+
+#ifndef GAMMA
+
+/* Maximum supported entries from jvm.cfg. */
+#define INIT_MAX_KNOWN_VMS      10
+/* Values for vmdesc.flag */
+#define VM_UNKNOWN              -1
+#define VM_KNOWN                 0
+#define VM_ALIASED_TO            1
+#define VM_WARN                  2
+#define VM_ERROR                 3
+#define VM_IF_SERVER_CLASS       4
+#define VM_IGNORE                5
+struct vmdesc {
+    char *name;
+    int flag;
+    char *alias;
+    char *server_class;
+};
+static struct vmdesc *knownVMs = NULL;
+static int knownVMsCount = 0;
+static int knownVMsLimit = 0;
+
+static void GrowKnownVMs();
+static int  KnownVMIndex(const char* name);
+static void FreeKnownVMs();
+static void ShowSplashScreen();
+
+#endif /* ifndef GAMMA */
+
+jboolean ServerClassMachine();
+
+/* flag which if set suppresses error messages from the launcher */
+static int noExitErrorMessage = 0;
+
+/*
+ * Running Java code in primordial thread caused many problems. We will
+ * create a new thread to invoke JVM. See 6316197 for more information.
+ */
+static jlong threadStackSize = 0;  /* stack size of the new thread */
+
+int JNICALL JavaMain(void * args); /* entry point                  */
+
+struct JavaMainArgs {
+  int     argc;
+  char ** argv;
+  char *  jarfile;
+  char *  classname;
+  InvocationFunctions ifn;
+};
+
+/*
+ * Entry point.
+ */
+int
+main(int argc, char ** argv)
+{
+    char *jarfile = 0;
+    char *classname = 0;
+    char *s = 0;
+    char *main_class = NULL;
+    int ret;
+    InvocationFunctions ifn;
+    jlong start, end;
+    char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN];
+    char ** original_argv = argv;
+
+    if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) {
+        _launcher_debug = JNI_TRUE;
+        printf("----_JAVA_LAUNCHER_DEBUG----\n");
+    }
+
+#ifndef GAMMA
+    /*
+     * 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
+     *     was issued).
+     *  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
+     *     bugid 5030265 below.)
+     */
+    SelectVersion(argc, argv, &main_class);
+#endif /* ifndef GAMMA */
+
+    /* copy original argv */
+    {
+      int i;
+      original_argv = (char**)JLI_MemAlloc(sizeof(char*)*(argc+1));
+      for(i = 0; i < argc+1; i++)
+        original_argv[i] = argv[i];
+    }
+
+    CreateExecutionEnvironment(&argc, &argv,
+                               jrepath, sizeof(jrepath),
+                               jvmpath, sizeof(jvmpath),
+                               original_argv);
+
+    ifn.CreateJavaVM = 0;
+    ifn.GetDefaultJavaVMInitArgs = 0;
+
+    if (_launcher_debug)
+      start = CounterGet();
+    if (!LoadJavaVM(jvmpath, &ifn)) {
+      exit(6);
+    }
+    if (_launcher_debug) {
+      end   = CounterGet();
+      printf("%ld micro seconds to LoadJavaVM\n",
+             (long)(jint)Counter2Micros(end-start));
+    }
+
+#ifdef JAVA_ARGS  /* javac, jar and friends. */
+    progname = "java";
+#else             /* java, oldjava, javaw and friends */
+#ifdef PROGNAME
+    progname = PROGNAME;
+#else
+    progname = *argv;
+    if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) {
+        progname = s + 1;
+    }
+#endif /* PROGNAME */
+#endif /* JAVA_ARGS */
+    ++argv;
+    --argc;
+
+#ifdef JAVA_ARGS
+    /* Preprocess wrapper arguments */
+    TranslateApplicationArgs(&argc, &argv);
+    if (!AddApplicationOptions()) {
+        exit(1);
+    }
+#endif
+
+    /* Set default CLASSPATH */
+    if ((s = getenv("CLASSPATH")) == 0) {
+        s = ".";
+    }
+#ifndef JAVA_ARGS
+    SetClassPath(s);
+#endif
+
+    /*
+     *  Parse command line options; if the return value of
+     *  ParseArguments is false, the program should exit.
+     */
+    if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret, jvmpath)) {
+      exit(ret);
+    }
+
+    /* Override class path if -jar flag was specified */
+    if (jarfile != 0) {
+        SetClassPath(jarfile);
+    }
+
+    /* set the -Dsun.java.command pseudo property */
+    SetJavaCommandLineProp(classname, jarfile, argc, argv);
+
+    /* Set the -Dsun.java.launcher pseudo property */
+    SetJavaLauncherProp();
+
+    /* set the -Dsun.java.launcher.* platform properties */
+    SetJavaLauncherPlatformProps();
+
+#ifndef GAMMA
+    /* Show the splash screen if needed */
+    ShowSplashScreen();
+#endif
+
+    /*
+     * Done with all command line processing and potential re-execs so
+     * clean up the environment.
+     */
+    (void)UnsetEnv(ENV_ENTRY);
+#ifndef GAMMA
+    (void)UnsetEnv(SPLASH_FILE_ENV_ENTRY);
+    (void)UnsetEnv(SPLASH_JAR_ENV_ENTRY);
+
+    JLI_MemFree(splash_jar_entry);
+    JLI_MemFree(splash_file_entry);
+#endif
+
+    /*
+     * 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.
+     */
+    if (threadStackSize == 0) {
+      struct JDK1_1InitArgs args1_1;
+      memset((void*)&args1_1, 0, sizeof(args1_1));
+      args1_1.version = JNI_VERSION_1_1;
+      ifn.GetDefaultJavaVMInitArgs(&args1_1);  /* ignore return value */
+      if (args1_1.javaStackSize > 0) {
+         threadStackSize = args1_1.javaStackSize;
+      }
+    }
+
+    { /* Create a new thread to create JVM and invoke main method */
+      struct JavaMainArgs args;
+
+      args.argc = argc;
+      args.argv = argv;
+      args.jarfile = jarfile;
+      args.classname = classname;
+      args.ifn = ifn;
+
+      return ContinueInNewThread(JavaMain, threadStackSize, (void*)&args);
+    }
+}
+
+int JNICALL
+JavaMain(void * _args)
+{
+    struct JavaMainArgs *args = (struct JavaMainArgs *)_args;
+    int argc = args->argc;
+    char **argv = args->argv;
+    char *jarfile = args->jarfile;
+    char *classname = args->classname;
+    InvocationFunctions ifn = args->ifn;
+
+    JavaVM *vm = 0;
+    JNIEnv *env = 0;
+    jstring mainClassName;
+    jclass mainClass;
+    jmethodID mainID;
+    jobjectArray mainArgs;
+    int ret = 0;
+    jlong start, end;
+
+    /*
+     * 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.";
+    jboolean messageDest = JNI_FALSE;
+
+    /* Initialize the virtual machine */
+
+    if (_launcher_debug)
+        start = CounterGet();
+    if (!InitializeJVM(&vm, &env, &ifn)) {
+        ReportErrorMessage("Could not create the Java virtual machine.",
+                           JNI_TRUE);
+        exit(1);
+    }
+
+    if (printVersion || showVersion) {
+        PrintJavaVersion(env);
+        if ((*env)->ExceptionOccurred(env)) {
+            ReportExceptionDescription(env);
+            goto leave;
+        }
+        if (printVersion) {
+            ret = 0;
+            message = NULL;
+            goto leave;
+        }
+        if (showVersion) {
+            fprintf(stderr, "\n");
+        }
+    }
+
+    /* If the user specified neither a class name nor a JAR file */
+    if (jarfile == 0 && classname == 0) {
+        PrintUsage();
+        message = NULL;
+        goto leave;
+    }
+
+#ifndef GAMMA
+    FreeKnownVMs();  /* after last possible PrintUsage() */
+#endif
+
+    if (_launcher_debug) {
+        end   = CounterGet();
+        printf("%ld micro seconds to InitializeJVM\n",
+               (long)(jint)Counter2Micros(end-start));
+    }
+
+    /* At this stage, argc/argv have the applications' arguments */
+    if (_launcher_debug) {
+        int i = 0;
+        printf("Main-Class is '%s'\n", classname ? classname : "");
+        printf("Apps' argc is %d\n", argc);
+        for (; i < argc; i++) {
+            printf("    argv[%2d] = '%s'\n", i, argv[i]);
+        }
+    }
+
+    ret = 1;
+
+    /*
+     * 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
+     *          all environments,
+     *     2)   Remove the vestages of maintaining main_class through
+     *          the environment (and remove these comments).
+     */
+    if (jarfile != 0) {
+        mainClassName = GetMainClassName(env, jarfile);
+        if ((*env)->ExceptionOccurred(env)) {
+            ReportExceptionDescription(env);
+            goto leave;
+        }
+        if (mainClassName == NULL) {
+          const char * format = "Failed to load Main-Class manifest "
+                                "attribute from\n%s";
+          message = (char*)JLI_MemAlloc((strlen(format) + strlen(jarfile)) *
+                                    sizeof(char));
+          sprintf(message, format, jarfile);
+          messageDest = JNI_TRUE;
+          goto leave;
+        }
+        classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
+        if (classname == NULL) {
+            ReportExceptionDescription(env);
+            goto leave;
+        }
+        mainClass = LoadClass(env, classname);
+        if(mainClass == NULL) { /* exception occured */
+            const char * format = "Could not find the main class: %s. Program will exit.";
+            ReportExceptionDescription(env);
+            message = (char *)JLI_MemAlloc((strlen(format) +
+                                            strlen(classname)) * sizeof(char) );
+            messageDest = JNI_TRUE;
+            sprintf(message, format, classname);
+            goto leave;
+        }
+        (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
+    } else {
+      mainClassName = NewPlatformString(env, classname);
+      if (mainClassName == NULL) {
+        const char * format = "Failed to load Main Class: %s";
+        message = (char *)JLI_MemAlloc((strlen(format) + strlen(classname)) *
+                                   sizeof(char) );
+        sprintf(message, format, classname);
+        messageDest = JNI_TRUE;
+        goto leave;
+      }
+      classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
+      if (classname == NULL) {
+        ReportExceptionDescription(env);
+        goto leave;
+      }
+      mainClass = LoadClass(env, classname);
+      if(mainClass == NULL) { /* exception occured */
+        const char * format = "Could not find the main class: %s.  Program will exit.";
+        ReportExceptionDescription(env);
+        message = (char *)JLI_MemAlloc((strlen(format) +
+                                        strlen(classname)) * sizeof(char) );
+        messageDest = JNI_TRUE;
+        sprintf(message, format, classname);
+        goto leave;
+      }
+      (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
+    }
+
+    /* Get the application's main method */
+    mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
+                                       "([Ljava/lang/String;)V");
+    if (mainID == NULL) {
+        if ((*env)->ExceptionOccurred(env)) {
+            ReportExceptionDescription(env);
+        } else {
+          message = "No main method found in specified class.";
+          messageDest = JNI_TRUE;
+        }
+        goto leave;
+    }
+
+    {    /* Make sure the main method is public */
+        jint mods;
+        jmethodID mid;
+        jobject obj = (*env)->ToReflectedMethod(env, mainClass,
+                                                mainID, JNI_TRUE);
+
+        if( obj == NULL) { /* exception occurred */
+            ReportExceptionDescription(env);
+            goto leave;
+        }
+
+        mid =
+          (*env)->GetMethodID(env,
+                              (*env)->GetObjectClass(env, obj),
+                              "getModifiers", "()I");
+        if ((*env)->ExceptionOccurred(env)) {
+            ReportExceptionDescription(env);
+            goto leave;
+        }
+
+        mods = (*env)->CallIntMethod(env, obj, mid);
+        if ((mods & 1) == 0) { /* if (!Modifier.isPublic(mods)) ... */
+            message = "Main method not public.";
+            messageDest = JNI_TRUE;
+            goto leave;
+        }
+    }
+
+    /* Build argument array */
+    mainArgs = NewPlatformStringArray(env, argv, argc);
+    if (mainArgs == NULL) {
+        ReportExceptionDescription(env);
+        goto leave;
+    }
+
+    /* Invoke main method. */
+    (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
+
+    /*
+     * The launcher's exit code (in the absence of calls to
+     * System.exit) will be non-zero if main threw an exception.
+     */
+    ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
+
+    /*
+     * 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.
+     */
+    if ((*vm)->DetachCurrentThread(vm) != 0) {
+        message = "Could not detach main thread.";
+        messageDest = JNI_TRUE;
+        ret = 1;
+        goto leave;
+    }
+
+    message = NULL;
+
+ leave:
+    /*
+     * 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.
+     */
+    (*vm)->DestroyJavaVM(vm);
+
+    if(message != NULL && !noExitErrorMessage)
+      ReportErrorMessage(message, messageDest);
+    return ret;
+}
+
+#ifndef GAMMA
+/*
+ * 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.
+ */
+char *
+CheckJvmType(int *pargc, char ***argv, jboolean speculative) {
+    int i, argi;
+    int argc;
+    char **newArgv;
+    int newArgvIdx = 0;
+    int isVMType;
+    int jvmidx = -1;
+    char *jvmtype = getenv("JDK_ALTERNATE_VM");
+
+    argc = *pargc;
+
+    /* To make things simpler we always copy the argv array */
+    newArgv = JLI_MemAlloc((argc + 1) * sizeof(char *));
+
+    /* The program name is always present */
+    newArgv[newArgvIdx++] = (*argv)[0];
+
+    for (argi = 1; argi < argc; argi++) {
+        char *arg = (*argv)[argi];
+        isVMType = 0;
+
+#ifdef JAVA_ARGS
+        if (arg[0] != '-') {
+            newArgv[newArgvIdx++] = arg;
+            continue;
+        }
+#else
+        if (strcmp(arg, "-classpath") == 0 ||
+            strcmp(arg, "-cp") == 0) {
+            newArgv[newArgvIdx++] = arg;
+            argi++;
+            if (argi < argc) {
+                newArgv[newArgvIdx++] = (*argv)[argi];
+            }
+            continue;
+        }
+        if (arg[0] != '-') break;
+#endif
+
+        /* Did the user pass an explicit VM type? */
+        i = KnownVMIndex(arg);
+        if (i >= 0) {
+            jvmtype = knownVMs[jvmidx = i].name + 1; /* skip the - */
+            isVMType = 1;
+            *pargc = *pargc - 1;
+        }
+
+        /* Did the user specify an "alternate" VM? */
+        else if (strncmp(arg, "-XXaltjvm=", 10) == 0 || strncmp(arg, "-J-XXaltjvm=", 12) == 0) {
+            isVMType = 1;
+            jvmtype = arg+((arg[1]=='X')? 10 : 12);
+            jvmidx = -1;
+        }
+
+        if (!isVMType) {
+            newArgv[newArgvIdx++] = arg;
+        }
+    }
+
+    /*
+     * 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
+     * argc.
+     */
+    while (argi < argc) {
+        newArgv[newArgvIdx++] = (*argv)[argi];
+        argi++;
+    }
+
+    /* argv is null-terminated */
+    newArgv[newArgvIdx] = 0;
+
+    /* Copy back argv */
+    *argv = newArgv;
+    *pargc = newArgvIdx;
+
+    /* use the default VM type if not specified (no alias processing) */
+    if (jvmtype == NULL) {
+      char* result = knownVMs[0].name+1;
+      /* Use a different VM type if we are on a server class machine? */
+      if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) &&
+          (ServerClassMachine() == JNI_TRUE)) {
+        result = knownVMs[0].server_class+1;
+      }
+      if (_launcher_debug) {
+        printf("Default VM: %s\n", result);
+      }
+      return result;
+    }
+
+    /* if using an alternate VM, no alias processing */
+    if (jvmidx < 0)
+      return jvmtype;
+
+    /* Resolve aliases first */
+    {
+      int loopCount = 0;
+      while (knownVMs[jvmidx].flag == VM_ALIASED_TO) {
+        int nextIdx = KnownVMIndex(knownVMs[jvmidx].alias);
+
+        if (loopCount > knownVMsCount) {
+          if (!speculative) {
+            ReportErrorMessage("Error: Corrupt jvm.cfg file; cycle in alias list.",
+                               JNI_TRUE);
+            exit(1);
+          } else {
+            return "ERROR";
+            /* break; */
+          }
+        }
+
+        if (nextIdx < 0) {
+          if (!speculative) {
+            ReportErrorMessage2("Error: Unable to resolve VM alias %s",
+                                knownVMs[jvmidx].alias, JNI_TRUE);
+            exit(1);
+          } else {
+            return "ERROR";
+          }
+        }
+        jvmidx = nextIdx;
+        jvmtype = knownVMs[jvmidx].name+1;
+        loopCount++;
+      }
+    }
+
+    switch (knownVMs[jvmidx].flag) {
+    case VM_WARN:
+        if (!speculative) {
+            fprintf(stderr, "Warning: %s VM not supported; %s VM will be used\n",
+                    jvmtype, knownVMs[0].name + 1);
+        }
+        /* fall through */
+    case VM_IGNORE:
+        jvmtype = knownVMs[jvmidx=0].name + 1;
+        /* fall through */
+    case VM_KNOWN:
+        break;
+    case VM_ERROR:
+        if (!speculative) {
+            ReportErrorMessage2("Error: %s VM not supported", jvmtype, JNI_TRUE);
+            exit(1);
+        } else {
+            return "ERROR";
+        }
+    }
+
+    return jvmtype;
+}
+#endif /* ifndef GAMMA */
+
+# define KB (1024UL)
+# define MB (1024UL * KB)
+# define GB (1024UL * MB)
+
+/* copied from HotSpot function "atomll()" */
+static int
+parse_stack_size(const char *s, jlong *result) {
+  jlong n = 0;
+  int args_read = sscanf(s, jlong_format_specifier(), &n);
+  if (args_read != 1) {
+    return 0;
+  }
+  while (*s != '\0' && *s >= '0' && *s <= '9') {
+    s++;
+  }
+  // 4705540: illegal if more characters are found after the first non-digit
+  if (strlen(s) > 1) {
+    return 0;
+  }
+  switch (*s) {
+    case 'T': case 't':
+      *result = n * GB * KB;
+      return 1;
+    case 'G': case 'g':
+      *result = n * GB;
+      return 1;
+    case 'M': case 'm':
+      *result = n * MB;
+      return 1;
+    case 'K': case 'k':
+      *result = n * KB;
+      return 1;
+    case '\0':
+      *result = n;
+      return 1;
+    default:
+      /* Create JVM with default stack and let VM handle malformed -Xss string*/
+      return 0;
+  }
+}
+
+/*
+ * Adds a new VM option with the given given name and value.
+ */
+void
+AddOption(char *str, void *info)
+{
+    /*
+     * Expand options array if needed to accommodate at least one more
+     * VM option.
+     */
+    if (numOptions >= maxOptions) {
+        if (options == 0) {
+            maxOptions = 4;
+            options = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption));
+        } else {
+            JavaVMOption *tmp;
+            maxOptions *= 2;
+            tmp = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption));
+            memcpy(tmp, options, numOptions * sizeof(JavaVMOption));
+            JLI_MemFree(options);
+            options = tmp;
+        }
+    }
+    options[numOptions].optionString = str;
+    options[numOptions++].extraInfo = info;
+
+    if (strncmp(str, "-Xss", 4) == 0) {
+      jlong tmp;
+      if (parse_stack_size(str + 4, &tmp)) {
+        threadStackSize = tmp;
+      }
+    }
+}
+
+static void
+SetClassPath(const char *s)
+{
+    char *def;
+    s = JLI_WildcardExpandClasspath(s);
+    def = JLI_MemAlloc(strlen(s) + 40);
+    sprintf(def, "-Djava.class.path=%s", s);
+    AddOption(def, NULL);
+}
+
+#ifndef GAMMA
+/*
+ * 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.
+ */
+static void
+SelectVersion(int argc, char **argv, char **main_class)
+{
+    char    *arg;
+    char    **new_argv;
+    char    **new_argp;
+    char    *operand;
+    char    *version = NULL;
+    char    *jre = NULL;
+    int     jarflag = 0;
+    int     headlessflag = 0;
+    int     restrict_search = -1;               /* -1 implies not known */
+    manifest_info info;
+    char    env_entry[MAXNAMELEN + 24] = ENV_ENTRY "=";
+    char    *splash_file_name = NULL;
+    char    *splash_jar_name = NULL;
+    char    *env_in;
+    int     res;
+
+    /*
+     * If the version has already been selected, set *main_class
+     * with the value passed through the environment (if any) and
+     * simply return.
+     */
+    if ((env_in = getenv(ENV_ENTRY)) != NULL) {
+        if (*env_in != '\0')
+            *main_class = JLI_StringDup(env_in);
+        return;
+    }
+
+    /*
+     * Scan through the arguments for options relevant to multiple JRE
+     * support.  For reference, the command line syntax is defined as:
+     *
+     * SYNOPSIS
+     *      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.
+     */
+    new_argv = JLI_MemAlloc((argc + 1) * sizeof(char*));
+    new_argv[0] = argv[0];
+    new_argp = &new_argv[1];
+    argc--;
+    argv++;
+    while ((arg = *argv) != 0 && *arg == '-') {
+        if (strncmp(arg, "-version:", 9) == 0) {
+            version = arg + 9;
+        } else if (strcmp(arg, "-jre-restrict-search") == 0) {
+            restrict_search = 1;
+        } else if (strcmp(arg, "-no-jre-restrict-search") == 0) {
+            restrict_search = 0;
+        } else {
+            if (strcmp(arg, "-jar") == 0)
+                jarflag = 1;
+            /* deal with "unfortunate" classpath syntax */
+            if ((strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) &&
+              (argc >= 2)) {
+                *new_argp++ = arg;
+                argc--;
+                argv++;
+                arg = *argv;
+            }
+
+            /*
+             * Checking for headless toolkit option in the some way as AWT does:
+             * "true" means true and any other value means false
+             */
+            if (strcmp(arg, "-Djava.awt.headless=true") == 0) {
+                headlessflag = 1;
+            } else if (strncmp(arg, "-Djava.awt.headless=", 20) == 0) {
+                headlessflag = 0;
+            } else if (strncmp(arg, "-splash:", 8) == 0) {
+                splash_file_name = arg+8;
+            }
+            *new_argp++ = arg;
+        }
+        argc--;
+        argv++;
+    }
+    if (argc <= 0) {    /* No operand? Possibly legit with -[full]version */
+        operand = NULL;
+    } else {
+        argc--;
+        *new_argp++ = operand = *argv++;
+    }
+    while (argc-- > 0)  /* Copy over [argument...] */
+        *new_argp++ = *argv++;
+    *new_argp = NULL;
+
+    /*
+     * 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
+     * this data around.
+     */
+    if (jarflag && operand) {
+        if ((res = JLI_ParseManifest(operand, &info)) != 0) {
+            if (res == -1)
+                ReportErrorMessage2("Unable to access jarfile %s",
+                  operand, JNI_TRUE);
+            else
+                ReportErrorMessage2("Invalid or corrupt jarfile %s",
+                  operand, JNI_TRUE);
+            exit(1);
+        }
+
+        /*
+         * 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
+         * line parsing
+         */
+        if (!headlessflag && !splash_file_name && info.splashscreen_image_file_name) {
+            splash_file_name = info.splashscreen_image_file_name;
+            splash_jar_name = operand;
+        }
+    } else {
+        info.manifest_version = NULL;
+        info.main_class = NULL;
+        info.jre_version = NULL;
+        info.jre_restrict_search = 0;
+    }
+
+    /*
+     * Passing on splash screen info in environment variables
+     */
+    if (splash_file_name && !headlessflag) {
+        char* splash_file_entry = JLI_MemAlloc(strlen(SPLASH_FILE_ENV_ENTRY "=")+strlen(splash_file_name)+1);
+        strcpy(splash_file_entry, SPLASH_FILE_ENV_ENTRY "=");
+        strcat(splash_file_entry, splash_file_name);
+        putenv(splash_file_entry);
+    }
+    if (splash_jar_name && !headlessflag) {
+        char* splash_jar_entry = JLI_MemAlloc(strlen(SPLASH_JAR_ENV_ENTRY "=")+strlen(splash_jar_name)+1);
+        strcpy(splash_jar_entry, SPLASH_JAR_ENV_ENTRY "=");
+        strcat(splash_jar_entry, splash_jar_name);
+        putenv(splash_jar_entry);
+    }
+
+    /*
+     * The JRE-Version and JRE-Restrict-Search values (if any) from the
+     * manifest are overwritten by any specified on the command line.
+     */
+    if (version != NULL)
+        info.jre_version = version;
+    if (restrict_search != -1)
+        info.jre_restrict_search = restrict_search;
+
+    /*
+     * "Valid" returns (other than unrecoverable errors) follow.  Set
+     * main_class as a side-effect of this routine.
+     */
+    if (info.main_class != NULL)
+        *main_class = JLI_StringDup(info.main_class);
+
+    /*
+     * If no version selection information is found either on the command
+     * line or in the manifest, simply return.
+     */
+    if (info.jre_version == NULL) {
+        JLI_FreeManifest();
+        JLI_MemFree(new_argv);
+        return;
+    }
+
+    /*
+     * Check for correct syntax of the version specification (JSR 56).
+     */
+    if (!JLI_ValidVersionString(info.jre_version)) {
+        ReportErrorMessage2("Syntax error in version specification \"%s\"",
+          info.jre_version, JNI_TRUE);
+        exit(1);
+    }
+
+    /*
+     * 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
+     * JRE support.
+     */
+    jre = LocateJRE(&info);
+    if (_launcher_debug)
+        printf("JRE-Version = %s, JRE-Restrict-Search = %s Selected = %s\n",
+          (info.jre_version?info.jre_version:"null"),
+          (info.jre_restrict_search?"true":"false"), (jre?jre:"null"));
+    if (jre == NULL) {
+        if (JLI_AcceptableRelease(FULL_VERSION, info.jre_version)) {
+            JLI_FreeManifest();
+            JLI_MemFree(new_argv);
+            return;
+        } else {
+            ReportErrorMessage2(
+              "Unable to locate JRE meeting specification \"%s\"",
+              info.jre_version, JNI_TRUE);
+            exit(1);
+        }
+    }
+
+    /*
+     * 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
+     * times.
+     */
+    if (info.main_class != NULL) {
+        if (strlen(info.main_class) <= MAXNAMELEN) {
+            (void)strcat(env_entry, info.main_class);
+        } else {
+            ReportErrorMessage("Error: main-class: attribute exceeds system limits\n", JNI_TRUE);
+            exit(1);
+        }
+    }
+    (void)putenv(env_entry);
+    ExecJRE(jre, new_argv);
+    JLI_FreeManifest();
+    JLI_MemFree(new_argv);
+    return;
+}
+#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
+ * 0 for a normal exit.
+ */
+static jboolean
+ParseArguments(int *pargc, char ***pargv, char **pjarfile,
+                       char **pclassname, int *pret, const char *jvmpath)
+{
+    int argc = *pargc;
+    char **argv = *pargv;
+    jboolean jarflag = JNI_FALSE;
+    char *arg;
+
+    *pret = 1;
+    while ((arg = *argv) != 0 && *arg == '-') {
+        argv++; --argc;
+        if (strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) {
+            if (argc < 1) {
+                ReportErrorMessage2("%s requires class path specification",
+                                    arg, JNI_TRUE);
+                PrintUsage();
+                return JNI_FALSE;
+            }
+            SetClassPath(*argv);
+            argv++; --argc;
+        } else if (strcmp(arg, "-jar") == 0) {
+            jarflag = JNI_TRUE;
+        } else if (strcmp(arg, "-help") == 0 ||
+                   strcmp(arg, "-h") == 0 ||
+                   strcmp(arg, "-?") == 0) {
+            PrintUsage();
+            *pret = 0;
+            return JNI_FALSE;
+        } else if (strcmp(arg, "-version") == 0) {
+            printVersion = JNI_TRUE;
+            return JNI_TRUE;
+        } else if (strcmp(arg, "-showversion") == 0) {
+            showVersion = JNI_TRUE;
+        } else if (strcmp(arg, "-X") == 0) {
+            *pret = PrintXUsage(jvmpath);
+            return JNI_FALSE;
+/*
+ * The following case provide backward compatibility with old-style
+ * command line options.
+ */
+        } else if (strcmp(arg, "-fullversion") == 0) {
+            fprintf(stderr, "%s full version \"%s\"\n", progname,
+                    FULL_VERSION);
+            *pret = 0;
+            return JNI_FALSE;
+        } else if (strcmp(arg, "-verbosegc") == 0) {
+            AddOption("-verbose:gc", NULL);
+        } else if (strcmp(arg, "-t") == 0) {
+            AddOption("-Xt", NULL);
+        } else if (strcmp(arg, "-tm") == 0) {
+            AddOption("-Xtm", NULL);
+        } else if (strcmp(arg, "-debug") == 0) {
+            AddOption("-Xdebug", NULL);
+        } else if (strcmp(arg, "-noclassgc") == 0) {
+            AddOption("-Xnoclassgc", NULL);
+        } else if (strcmp(arg, "-Xfuture") == 0) {
+            AddOption("-Xverify:all", NULL);
+        } else if (strcmp(arg, "-verify") == 0) {
+            AddOption("-Xverify:all", NULL);
+        } else if (strcmp(arg, "-verifyremote") == 0) {
+            AddOption("-Xverify:remote", NULL);
+        } else if (strcmp(arg, "-noverify") == 0) {
+            AddOption("-Xverify:none", NULL);
+        } else if (strcmp(arg, "-XXsuppressExitMessage") == 0) {
+            noExitErrorMessage = 1;
+        } else if (strncmp(arg, "-prof", 5) == 0) {
+            char *p = arg + 5;
+            char *tmp = JLI_MemAlloc(strlen(arg) + 50);
+            if (*p) {
+                sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1);
+            } else {
+                sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof");
+            }
+            AddOption(tmp, NULL);
+        } else if (strncmp(arg, "-ss", 3) == 0 ||
+                   strncmp(arg, "-oss", 4) == 0 ||
+                   strncmp(arg, "-ms", 3) == 0 ||
+                   strncmp(arg, "-mx", 3) == 0) {
+            char *tmp = JLI_MemAlloc(strlen(arg) + 6);
+            sprintf(tmp, "-X%s", arg + 1); /* skip '-' */
+            AddOption(tmp, NULL);
+        } else if (strcmp(arg, "-checksource") == 0 ||
+                   strcmp(arg, "-cs") == 0 ||
+                   strcmp(arg, "-noasyncgc") == 0) {
+            /* No longer supported */
+            fprintf(stderr,
+                    "Warning: %s option is no longer supported.\n",
+                    arg);
+        } else if (strncmp(arg, "-version:", 9) == 0 ||
+                   strcmp(arg, "-no-jre-restrict-search") == 0 ||
+                   strcmp(arg, "-jre-restrict-search") == 0 ||
+                   strncmp(arg, "-splash:", 8) == 0) {
+            ; /* Ignore machine independent options already handled */
+        } else if (RemovableMachineDependentOption(arg) ) {
+            ; /* Do not pass option to vm. */
+        }
+        else {
+            AddOption(arg, NULL);
+        }
+    }
+
+    if (--argc >= 0) {
+        if (jarflag) {
+            *pjarfile = *argv++;
+            *pclassname = 0;
+        } else {
+            *pjarfile = 0;
+            *pclassname = *argv++;
+        }
+        *pargc = argc;
+        *pargv = argv;
+    }
+
+    return JNI_TRUE;
+}
+
+/*
+ * Initializes the Java Virtual Machine. Also frees options array when
+ * finished.
+ */
+static jboolean
+InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn)
+{
+    JavaVMInitArgs args;
+    jint r;
+
+    memset(&args, 0, sizeof(args));
+    args.version  = JNI_VERSION_1_2;
+    args.nOptions = numOptions;
+    args.options  = options;
+    args.ignoreUnrecognized = JNI_FALSE;
+
+    if (_launcher_debug) {
+        int i = 0;
+        printf("JavaVM args:\n    ");
+        printf("version 0x%08lx, ", (long)args.version);
+        printf("ignoreUnrecognized is %s, ",
+               args.ignoreUnrecognized ? "JNI_TRUE" : "JNI_FALSE");
+        printf("nOptions is %ld\n", (long)args.nOptions);
+        for (i = 0; i < numOptions; i++)
+            printf("    option[%2d] = '%s'\n",
+                   i, args.options[i].optionString);
+    }
+
+    r = ifn->CreateJavaVM(pvm, (void **)penv, &args);
+    JLI_MemFree(options);
+    return r == JNI_OK;
+}
+
+
+#define NULL_CHECK0(e) if ((e) == 0) return 0
+#define NULL_CHECK(e) if ((e) == 0) return
+
+static jstring platformEncoding = NULL;
+static jstring getPlatformEncoding(JNIEnv *env) {
+    if (platformEncoding == NULL) {
+        jstring propname = (*env)->NewStringUTF(env, "sun.jnu.encoding");
+        if (propname) {
+            jclass cls;
+            jmethodID mid;
+            NULL_CHECK0 (cls = (*env)->FindClass(env, "java/lang/System"));
+            NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
+                                   env, cls,
+                                   "getProperty",
+                                   "(Ljava/lang/String;)Ljava/lang/String;"));
+            platformEncoding = (*env)->CallStaticObjectMethod (
+                                    env, cls, mid, propname);
+        }
+    }
+    return platformEncoding;
+}
+
+static jboolean isEncodingSupported(JNIEnv *env, jstring enc) {
+    jclass cls;
+    jmethodID mid;
+    NULL_CHECK0 (cls = (*env)->FindClass(env, "java/nio/charset/Charset"));
+    NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
+                           env, cls,
+                           "isSupported",
+                           "(Ljava/lang/String;)Z"));
+    return (*env)->CallStaticBooleanMethod(env, cls, mid, enc);
+}
+
+/*
+ * Returns a new Java string object for the specified platform string.
+ */
+static jstring
+NewPlatformString(JNIEnv *env, char *s)
+{
+    int len = (int)strlen(s);
+    jclass cls;
+    jmethodID mid;
+    jbyteArray ary;
+    jstring enc;
+
+    if (s == NULL)
+        return 0;
+    enc = getPlatformEncoding(env);
+
+    ary = (*env)->NewByteArray(env, len);
+    if (ary != 0) {
+        jstring str = 0;
+        (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s);
+        if (!(*env)->ExceptionOccurred(env)) {
+            if (isEncodingSupported(env, enc) == JNI_TRUE) {
+                NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
+                NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
+                                          "([BLjava/lang/String;)V"));
+                str = (*env)->NewObject(env, cls, mid, ary, enc);
+            } else {
+                /*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.
+                */
+                NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
+                NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
+                                          "([B)V"));
+                str = (*env)->NewObject(env, cls, mid, ary);
+            }
+            (*env)->DeleteLocalRef(env, ary);
+            return str;
+        }
+    }
+    return 0;
+}
+
+/*
+ * Returns a new array of Java string objects for the specified
+ * array of platform strings.
+ */
+static jobjectArray
+NewPlatformStringArray(JNIEnv *env, char **strv, int strc)
+{
+    jarray cls;
+    jarray ary;
+    int i;
+
+    NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
+    NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0));
+    for (i = 0; i < strc; i++) {
+        jstring str = NewPlatformString(env, *strv++);
+        NULL_CHECK0(str);
+        (*env)->SetObjectArrayElement(env, ary, i, str);
+        (*env)->DeleteLocalRef(env, str);
+    }
+    return ary;
+}
+
+/*
+ * Loads a class, convert the '.' to '/'.
+ */
+static jclass
+LoadClass(JNIEnv *env, char *name)
+{
+    char *buf = JLI_MemAlloc(strlen(name) + 1);
+    char *s = buf, *t = name, c;
+    jclass cls;
+    jlong start, end;
+
+    if (_launcher_debug)
+        start = CounterGet();
+
+    do {
+        c = *t++;
+        *s++ = (c == '.') ? '/' : c;
+    } while (c != '\0');
+    cls = (*env)->FindClass(env, buf);
+    JLI_MemFree(buf);
+
+    if (_launcher_debug) {
+        end   = CounterGet();
+        printf("%ld micro seconds to load main class\n",
+               (long)(jint)Counter2Micros(end-start));
+        printf("----_JAVA_LAUNCHER_DEBUG----\n");
+    }
+
+    return cls;
+}
+
+
+/*
+ * Returns the main class name for the specified jar file.
+ */
+static jstring
+GetMainClassName(JNIEnv *env, char *jarname)
+{
+#define MAIN_CLASS "Main-Class"
+    jclass cls;
+    jmethodID mid;
+    jobject jar, man, attr;
+    jstring str, result = 0;
+
+    NULL_CHECK0(cls = (*env)->FindClass(env, "java/util/jar/JarFile"));
+    NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
+                                          "(Ljava/lang/String;)V"));
+    NULL_CHECK0(str = NewPlatformString(env, jarname));
+    NULL_CHECK0(jar = (*env)->NewObject(env, cls, mid, str));
+    NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "getManifest",
+                                          "()Ljava/util/jar/Manifest;"));
+    man = (*env)->CallObjectMethod(env, jar, mid);
+    if (man != 0) {
+        NULL_CHECK0(mid = (*env)->GetMethodID(env,
+                                    (*env)->GetObjectClass(env, man),
+                                    "getMainAttributes",
+                                    "()Ljava/util/jar/Attributes;"));
+        attr = (*env)->CallObjectMethod(env, man, mid);
+        if (attr != 0) {
+            NULL_CHECK0(mid = (*env)->GetMethodID(env,
+                                    (*env)->GetObjectClass(env, attr),
+                                    "getValue",
+                                    "(Ljava/lang/String;)Ljava/lang/String;"));
+            NULL_CHECK0(str = NewPlatformString(env, MAIN_CLASS));
+            result = (*env)->CallObjectMethod(env, attr, mid, str);
+        }
+    }
+    return result;
+}
+
+#ifdef JAVA_ARGS
+static char *java_args[] = JAVA_ARGS;
+static char *app_classpath[] = APP_CLASSPATH;
+
+/*
+ * For tools, convert command line args thus:
+ *   javac -cp foo:foo/"*" -J-ms32m ...
+ *   java -ms32m -cp JLI_WildcardExpandClasspath(foo:foo/"*") ...
+ */
+static void
+TranslateApplicationArgs(int *pargc, char ***pargv)
+{
+    const int NUM_ARGS = (sizeof(java_args) / sizeof(char *));
+    int argc = *pargc;
+    char **argv = *pargv;
+    int nargc = argc + NUM_ARGS;
+    char **nargv = JLI_MemAlloc((nargc + 1) * sizeof(char *));
+    int i;
+
+    *pargc = nargc;
+    *pargv = nargv;
+
+    /* Copy the VM arguments (i.e. prefixed with -J) */
+    for (i = 0; i < NUM_ARGS; i++) {
+        char *arg = java_args[i];
+        if (arg[0] == '-' && arg[1] == 'J') {
+            *nargv++ = arg + 2;
+        }
+    }
+
+    for (i = 0; i < argc; i++) {
+        char *arg = argv[i];
+        if (arg[0] == '-' && arg[1] == 'J') {
+            if (arg[2] == '\0') {
+                ReportErrorMessage("Error: the -J option should not be "
+                                   "followed by a space.", JNI_TRUE);
+                exit(1);
+            }
+            *nargv++ = arg + 2;
+        }
+    }
+
+    /* Copy the rest of the arguments */
+    for (i = 0; i < NUM_ARGS; i++) {
+        char *arg = java_args[i];
+        if (arg[0] != '-' || arg[1] != 'J') {
+            *nargv++ = arg;
+        }
+    }
+    for (i = 0; i < argc; i++) {
+        char *arg = argv[i];
+        if (arg[0] == '-') {
+            if (arg[1] == 'J')
+                continue;
+#ifdef EXPAND_CLASSPATH_WILDCARDS
+            if (arg[1] == 'c'
+                && (strcmp(arg, "-cp") == 0 ||
+                    strcmp(arg, "-classpath") == 0)
+                && i < argc - 1) {
+                *nargv++ = arg;
+                *nargv++ = (char *) JLI_WildcardExpandClasspath(argv[i+1]);
+                i++;
+                continue;
+            }
+#endif
+        }
+        *nargv++ = arg;
+    }
+    *nargv = 0;
+}
+
+/*
+ * For our tools, we try to add 3 VM options:
+ *      -Denv.class.path=<envcp>
+ *      -Dapplication.home=<apphome>
+ *      -Djava.class.path=<appcp>
+ * <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 classes (sun.tools.javac.Main) only if they explicitly add
+ *           tools.jar to CLASSPATH.
+ * <apphome> is the directory where the application is installed.
+ * <appcp>   is the classpath to where our apps' classfiles are.
+ */
+static jboolean
+AddApplicationOptions()
+{
+    const int NUM_APP_CLASSPATH = (sizeof(app_classpath) / sizeof(char *));
+    char *envcp, *appcp, *apphome;
+    char home[MAXPATHLEN]; /* application home */
+    char separator[] = { PATH_SEPARATOR, '\0' };
+    int size, i;
+    int strlenHome;
+
+    {
+        const char *s = getenv("CLASSPATH");
+        if (s) {
+            s = (char *) JLI_WildcardExpandClasspath(s);
+            /* 40 for -Denv.class.path= */
+            envcp = (char *)JLI_MemAlloc(strlen(s) + 40);
+            sprintf(envcp, "-Denv.class.path=%s", s);
+            AddOption(envcp, NULL);
+        }
+    }
+
+    if (!GetApplicationHome(home, sizeof(home))) {
+        ReportErrorMessage("Can't determine application home", JNI_TRUE);
+        return JNI_FALSE;
+    }
+
+    /* 40 for '-Dapplication.home=' */
+    apphome = (char *)JLI_MemAlloc(strlen(home) + 40);
+    sprintf(apphome, "-Dapplication.home=%s", home);
+    AddOption(apphome, NULL);
+
+    /* How big is the application's classpath? */
+    size = 40;                                 /* 40: "-Djava.class.path=" */
+    strlenHome = (int)strlen(home);
+    for (i = 0; i < NUM_APP_CLASSPATH; i++) {
+        size += strlenHome + (int)strlen(app_classpath[i]) + 1; /* 1: separator */
+    }
+    appcp = (char *)JLI_MemAlloc(size + 1);
+    strcpy(appcp, "-Djava.class.path=");
+    for (i = 0; i < NUM_APP_CLASSPATH; i++) {
+        strcat(appcp, home);                    /* c:\program files\myapp */
+        strcat(appcp, app_classpath[i]);        /* \lib\myapp.jar         */
+        strcat(appcp, separator);               /* ;                      */
+    }
+    appcp[strlen(appcp)-1] = '\0';  /* remove trailing path separator */
+    AddOption(appcp, NULL);
+    return JNI_TRUE;
+}
+#endif /* JAVA_ARGS */
+
+/*
+ * 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.
+ */
+void
+SetJavaCommandLineProp(char *classname, char *jarfile,
+                       int argc, char **argv)
+{
+
+    int i = 0;
+    size_t len = 0;
+    char* javaCommand = NULL;
+    char* dashDstr = "-Dsun.java.command=";
+
+    if (classname == NULL && jarfile == NULL) {
+        /* unexpected, one of these should be set. just return without
+         * setting the property
+         */
+        return;
+    }
+
+    /* if the class name is not set, then use the jarfile name */
+    if (classname == NULL) {
+        classname = jarfile;
+    }
+
+    /* determine the amount of memory to allocate assuming
+     * the individual components will be space separated
+     */
+    len = strlen(classname);
+    for (i = 0; i < argc; i++) {
+        len += strlen(argv[i]) + 1;
+    }
+
+    /* allocate the memory */
+    javaCommand = (char*) JLI_MemAlloc(len + strlen(dashDstr) + 1);
+
+    /* build the -D string */
+    *javaCommand = '\0';
+    strcat(javaCommand, dashDstr);
+    strcat(javaCommand, classname);
+
+    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.
+         */
+        strcat(javaCommand, " ");
+        strcat(javaCommand, argv[i]);
+    }
+
+    AddOption(javaCommand, NULL);
+}
+
+/*
+ * 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.
+ */
+void SetJavaLauncherProp() {
+  AddOption("-Dsun.java.launcher=" LAUNCHER_TYPE, NULL);
+}
+
+/*
+ * Prints the version information from the java.version and other properties.
+ */
+static void
+PrintJavaVersion(JNIEnv *env)
+{
+    jclass ver;
+    jmethodID print;
+
+    NULL_CHECK(ver = (*env)->FindClass(env, "sun/misc/Version"));
+    NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, "print", "()V"));
+
+    (*env)->CallStaticVoidMethod(env, ver, print);
+}
+
+/*
+ * Prints default usage message.
+ */
+static void
+PrintUsage(void)
+{
+#ifndef GAMMA
+    int i;
+#endif
+
+    fprintf(stdout,
+        "Usage: %s [-options] class [args...]\n"
+        "           (to execute a class)\n"
+        "   or  %s [-options] -jar jarfile [args...]\n"
+        "           (to execute a jar file)\n"
+        "\n"
+        "where options include:\n",
+        progname,
+        progname);
+
+#ifndef GAMMA
+    PrintMachineDependentOptions();
+
+    if ((knownVMs[0].flag == VM_KNOWN) ||
+        (knownVMs[0].flag == VM_IF_SERVER_CLASS)) {
+      fprintf(stdout, "    %s\t  to select the \"%s\" VM\n",
+              knownVMs[0].name, knownVMs[0].name+1);
+    }
+    for (i=1; i<knownVMsCount; i++) {
+        if (knownVMs[i].flag == VM_KNOWN)
+            fprintf(stdout, "    %s\t  to select the \"%s\" VM\n",
+                    knownVMs[i].name, knownVMs[i].name+1);
+    }
+    for (i=1; i<knownVMsCount; i++) {
+        if (knownVMs[i].flag == VM_ALIASED_TO)
+            fprintf(stdout, "    %s\t  is a synonym for "
+                    "the \"%s\" VM  [deprecated]\n",
+                    knownVMs[i].name, knownVMs[i].alias+1);
+    }
+    /* The first known VM is the default */
+    {
+      const char* defaultVM   = knownVMs[0].name+1;
+      const char* punctuation = ".";
+      const char* reason      = "";
+      if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) &&
+          (ServerClassMachine() == JNI_TRUE)) {
+        defaultVM = knownVMs[0].server_class+1;
+        punctuation = ", ";
+        reason = "because you are running on a server-class machine.\n";
+      }
+      fprintf(stdout, "                  The default VM is %s%s\n",
+              defaultVM, punctuation);
+      fprintf(stdout, "                  %s\n",
+              reason);
+    }
+#endif /* ifndef GAMMA */
+
+    fprintf(stdout,
+"    -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"
+"    -D<name>=<value>\n"
+"                  set a system property\n"
+"    -verbose[:class|gc|jni]\n"
+"                  enable verbose output\n"
+"    -version      print product version and exit\n"
+"    -version:<value>\n"
+"                  require the specified version to run\n"
+"    -showversion  print product version and continue\n"
+"    -jre-restrict-search | -jre-no-restrict-search\n"
+"                  include/exclude user private JREs in the version search\n"
+"    -? -help      print this help message\n"
+"    -X            print help on non-standard options\n"
+"    -ea[:<packagename>...|:<classname>]\n"
+"    -enableassertions[:<packagename>...|:<classname>]\n"
+"                  enable assertions\n"
+"    -da[:<packagename>...|:<classname>]\n"
+"    -disableassertions[:<packagename>...|:<classname>]\n"
+"                  disable assertions\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"
+"    -splash:<imagepath>\n"
+"                  show splash screen with specified image\n"
+
+            ,PATH_SEPARATOR);
+}
+
+/*
+ * Print usage message for -X options.
+ */
+static jint
+PrintXUsage(const char *jvmpath)
+{
+    /*
+       A 32 bit cushion to prevent buffer overrun, noting that
+       fopen(3C) may fail if the buffer exceeds MAXPATHLEN.
+    */
+    char path[MAXPATHLEN+32];
+    char buf[128];
+    size_t n;
+    FILE *fp;
+    static const char Xusage_txt[] = "/Xusage.txt";
+
+    strcpy(path, jvmpath);
+    /* Note the FILE_SEPARATOR is platform dependent */
+    strcpy(strrchr(path, FILE_SEPARATOR), Xusage_txt);
+    fp = fopen(path, "r");
+    if (fp == 0) {
+        fprintf(stderr, "Can't open %s\n", path);
+        return 1;
+    }
+    while ((n = fread(buf, 1, sizeof(buf), fp)) != 0) {
+        fwrite(buf, 1, n, stdout);
+    }
+    fclose(fp);
+    return 0;
+}
+
+#ifndef GAMMA
+/*
+ * 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:
+ *
+ *     jvmcfg         :=  { vmLine }
+ *     vmLine         :=  knownLine
+ *                    |   aliasLine
+ *                    |   warnLine
+ *                    |   ignoreLine
+ *                    |   errorLine
+ *                    |   predicateLine
+ *                    |   commentLine
+ *     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
+ *     flag           :=  "-" identifier
+ *
+ * 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
+ * mechanism.
+ */
+jint
+ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative)
+{
+    FILE *jvmCfg;
+    char jvmCfgName[MAXPATHLEN+20];
+    char line[MAXPATHLEN+20];
+    int cnt = 0;
+    int lineno = 0;
+    jlong start, end;
+    int vmType;
+    char *tmpPtr;
+    char *altVMName = NULL;
+    char *serverClassVMName = NULL;
+    static char *whiteSpace = " \t";
+    if (_launcher_debug) {
+        start = CounterGet();
+    }
+
+    strcpy(jvmCfgName, jrepath);
+    strcat(jvmCfgName, FILESEP "lib" FILESEP);
+    strcat(jvmCfgName, arch);
+    strcat(jvmCfgName, FILESEP "jvm.cfg");
+
+    jvmCfg = fopen(jvmCfgName, "r");
+    if (jvmCfg == NULL) {
+      if (!speculative) {
+        ReportErrorMessage2("Error: could not open `%s'", jvmCfgName,
+                            JNI_TRUE);
+        exit(1);
+      } else {
+        return -1;
+      }
+    }
+    while (fgets(line, sizeof(line), jvmCfg) != NULL) {
+        vmType = VM_UNKNOWN;
+        lineno++;
+        if (line[0] == '#')
+            continue;
+        if (line[0] != '-') {
+            fprintf(stderr, "Warning: no leading - on line %d of `%s'\n",
+                    lineno, jvmCfgName);
+        }
+        if (cnt >= knownVMsLimit) {
+            GrowKnownVMs(cnt);
+        }
+        line[strlen(line)-1] = '\0'; /* remove trailing newline */
+        tmpPtr = line + strcspn(line, whiteSpace);
+        if (*tmpPtr == 0) {
+            fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n",
+                    lineno, jvmCfgName);
+        } else {
+            /* Null-terminate this string for JLI_StringDup below */
+            *tmpPtr++ = 0;
+            tmpPtr += strspn(tmpPtr, whiteSpace);
+            if (*tmpPtr == 0) {
+                fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n",
+                        lineno, jvmCfgName);
+            } else {
+                if (!strncmp(tmpPtr, "KNOWN", strlen("KNOWN"))) {
+                    vmType = VM_KNOWN;
+                } else if (!strncmp(tmpPtr, "ALIASED_TO", strlen("ALIASED_TO"))) {
+                    tmpPtr += strcspn(tmpPtr, whiteSpace);
+                    if (*tmpPtr != 0) {
+                        tmpPtr += strspn(tmpPtr, whiteSpace);
+                    }
+                    if (*tmpPtr == 0) {
+                        fprintf(stderr, "Warning: missing VM alias on line %d of `%s'\n",
+                                lineno, jvmCfgName);
+                    } else {
+                        /* Null terminate altVMName */
+                        altVMName = tmpPtr;
+                        tmpPtr += strcspn(tmpPtr, whiteSpace);
+                        *tmpPtr = 0;
+                        vmType = VM_ALIASED_TO;
+                    }
+                } else if (!strncmp(tmpPtr, "WARN", strlen("WARN"))) {
+                    vmType = VM_WARN;
+                } else if (!strncmp(tmpPtr, "IGNORE", strlen("IGNORE"))) {
+                    vmType = VM_IGNORE;
+                } else if (!strncmp(tmpPtr, "ERROR", strlen("ERROR"))) {
+                    vmType = VM_ERROR;
+                } else if (!strncmp(tmpPtr,
+                                    "IF_SERVER_CLASS",
+                                    strlen("IF_SERVER_CLASS"))) {
+                    tmpPtr += strcspn(tmpPtr, whiteSpace);
+                    if (*tmpPtr != 0) {
+                        tmpPtr += strspn(tmpPtr, whiteSpace);
+                    }
+                    if (*tmpPtr == 0) {
+                        fprintf(stderr, "Warning: missing server class VM on line %d of `%s'\n",
+                                lineno, jvmCfgName);
+                    } else {
+                        /* Null terminate server class VM name */
+                        serverClassVMName = tmpPtr;
+                        tmpPtr += strcspn(tmpPtr, whiteSpace);
+                        *tmpPtr = 0;
+                        vmType = VM_IF_SERVER_CLASS;
+                    }
+                } else {
+                    fprintf(stderr, "Warning: unknown VM type on line %d of `%s'\n",
+                            lineno, &jvmCfgName[0]);
+                    vmType = VM_KNOWN;
+                }
+            }
+        }
+
+        if (_launcher_debug)
+            printf("jvm.cfg[%d] = ->%s<-\n", cnt, line);
+        if (vmType != VM_UNKNOWN) {
+            knownVMs[cnt].name = JLI_StringDup(line);
+            knownVMs[cnt].flag = vmType;
+            switch (vmType) {
+            default:
+                break;
+            case VM_ALIASED_TO:
+                knownVMs[cnt].alias = JLI_StringDup(altVMName);
+                if (_launcher_debug) {
+                    printf("    name: %s  vmType: %s  alias: %s\n",
+                           knownVMs[cnt].name, "VM_ALIASED_TO", knownVMs[cnt].alias);
+                }
+                break;
+            case VM_IF_SERVER_CLASS:
+                knownVMs[cnt].server_class = JLI_StringDup(serverClassVMName);
+                if (_launcher_debug) {
+                    printf("    name: %s  vmType: %s  server_class: %s\n",
+                           knownVMs[cnt].name, "VM_IF_SERVER_CLASS", knownVMs[cnt].server_class);
+                }
+                break;
+            }
+            cnt++;
+        }
+    }
+    fclose(jvmCfg);
+    knownVMsCount = cnt;
+
+    if (_launcher_debug) {
+        end   = CounterGet();
+        printf("%ld micro seconds to parse jvm.cfg\n",
+               (long)(jint)Counter2Micros(end-start));
+    }
+
+    return cnt;
+}
+
+
+static void
+GrowKnownVMs(int minimum)
+{
+    struct vmdesc* newKnownVMs;
+    int newMax;
+
+    newMax = (knownVMsLimit == 0 ? INIT_MAX_KNOWN_VMS : (2 * knownVMsLimit));
+    if (newMax <= minimum) {
+        newMax = minimum;
+    }
+    newKnownVMs = (struct vmdesc*) JLI_MemAlloc(newMax * sizeof(struct vmdesc));
+    if (knownVMs != NULL) {
+        memcpy(newKnownVMs, knownVMs, knownVMsLimit * sizeof(struct vmdesc));
+    }
+    JLI_MemFree(knownVMs);
+    knownVMs = newKnownVMs;
+    knownVMsLimit = newMax;
+}
+
+
+/* Returns index of VM or -1 if not found */
+static int
+KnownVMIndex(const char* name)
+{
+    int i;
+    if (strncmp(name, "-J", 2) == 0) name += 2;
+    for (i = 0; i < knownVMsCount; i++) {
+        if (!strcmp(name, knownVMs[i].name)) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+static void
+FreeKnownVMs()
+{
+    int i;
+    for (i = 0; i < knownVMsCount; i++) {
+        JLI_MemFree(knownVMs[i].name);
+        knownVMs[i].name = NULL;
+    }
+    JLI_MemFree(knownVMs);
+}
+
+
+/*
+ * Displays the splash screen according to the jar file name
+ * and image file names stored in environment variables
+ */
+static void
+ShowSplashScreen()
+{
+    const char *jar_name = getenv(SPLASH_JAR_ENV_ENTRY);
+    const char *file_name = getenv(SPLASH_FILE_ENV_ENTRY);
+    int data_size;
+    void *image_data;
+    if (jar_name) {
+        image_data = JLI_JarUnpackFile(jar_name, file_name, &data_size);
+        if (image_data) {
+            DoSplashInit();
+            DoSplashLoadMemory(image_data, data_size);
+            JLI_MemFree(image_data);
+        }
+    } else if (file_name) {
+        DoSplashInit();
+        DoSplashLoadFile(file_name);
+    } else {
+        return;
+    }
+    DoSplashSetFileJarName(file_name, jar_name);
+}
+
+#endif /* ifndef GAMMA */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/launcher/java.h	Thu Dec 02 05:45:54 2010 -0800
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+
+#ifndef _JAVA_H_
+#define _JAVA_H_
+
+/*
+ * Get system specific defines.
+ */
+#include "jni.h"
+#include "java_md.h"
+#include "jli_util.h"
+
+/*
+ * Pointers to the needed JNI invocation API, initialized by LoadJavaVM.
+ */
+typedef jint (JNICALL *CreateJavaVM_t)(JavaVM **pvm, void **env, void *args);
+typedef jint (JNICALL *GetDefaultJavaVMInitArgs_t)(void *args);
+
+typedef struct {
+    CreateJavaVM_t CreateJavaVM;
+    GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs;
+} InvocationFunctions;
+
+/*
+ * Prototypes for launcher functions in the system specific java_md.c.
+ */
+
+jboolean
+LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn);
+
+void
+GetXUsagePath(char *buf, jint bufsize);
+
+jboolean
+GetApplicationHome(char *buf, jint bufsize);
+
+const char *
+GetArch();
+
+void CreateExecutionEnvironment(int *_argc,
+                                       char ***_argv,
+                                       char jrepath[],
+                                       jint so_jrepath,
+                                       char jvmpath[],
+                                       jint so_jvmpath,
+                                       char **original_argv);
+
+/*
+ * Report an error message to stderr or a window as appropriate.  The
+ * flag always is set to JNI_TRUE if message is to be reported to both
+ * strerr and windows and set to JNI_FALSE if the message should only
+ * be sent to a window.
+ */
+void ReportErrorMessage(char * message, jboolean always);
+void ReportErrorMessage2(char * format, char * string, jboolean always);
+
+/*
+ * Report an exception which terminates the vm to stderr or a window
+ * as appropriate.
+ */
+void ReportExceptionDescription(JNIEnv * env);
+
+jboolean RemovableMachineDependentOption(char * option);
+void PrintMachineDependentOptions();
+
+const char *jlong_format_specifier();
+/*
+ * Block current thread and continue execution in new thread
+ */
+int ContinueInNewThread(int (JNICALL *continuation)(void *),
+                        jlong stack_size, void * args);
+
+/* sun.java.launcher.* platform properties. */
+void SetJavaLauncherPlatformProps(void);
+
+/*
+ * Functions defined in java.c and used in java_md.c.
+ */
+jint ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative);
+char *CheckJvmType(int *argc, char ***argv, jboolean speculative);
+void AddOption(char *str, void *info);
+
+/*
+ * Make launcher spit debug output.
+ */
+extern jboolean _launcher_debug;
+
+#endif /* _JAVA_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/launcher/jli_util.c	Thu Dec 02 05:45:54 2010 -0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "jli_util.h"
+
+#ifdef GAMMA
+#ifdef _WINDOWS
+#define strdup _strdup
+#endif
+#endif
+
+/*
+ * Returns a pointer to a block of at least 'size' bytes of memory.
+ * Prints error message and exits if the memory could not be allocated.
+ */
+void *
+JLI_MemAlloc(size_t size)
+{
+    void *p = malloc(size);
+    if (p == 0) {
+        perror("malloc");
+        exit(1);
+    }
+    return p;
+}
+
+/*
+ * Equivalent to realloc(size).
+ * Prints error message and exits if the memory could not be reallocated.
+ */
+void *
+JLI_MemRealloc(void *ptr, size_t size)
+{
+    void *p = realloc(ptr, size);
+    if (p == 0) {
+        perror("realloc");
+        exit(1);
+    }
+    return p;
+}
+
+/*
+ * Wrapper over strdup(3C) which prints an error message and exits if memory
+ * could not be allocated.
+ */
+char *
+JLI_StringDup(const char *s1)
+{
+    char *s = strdup(s1);
+    if (s == NULL) {
+        perror("strdup");
+        exit(1);
+    }
+    return s;
+}
+
+/*
+ * Very equivalent to free(ptr).
+ * Here to maintain pairing with the above routines.
+ */
+void
+JLI_MemFree(void *ptr)
+{
+    free(ptr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/launcher/jli_util.h	Thu Dec 02 05:45:54 2010 -0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef _JLI_UTIL_H
+#define _JLI_UTIL_H
+
+#include <stdlib.h>
+
+void *JLI_MemAlloc(size_t size);
+void *JLI_MemRealloc(void *ptr, size_t size);
+char *JLI_StringDup(const char *s1);
+void  JLI_MemFree(void *ptr);
+
+#endif  /* _JLI_UTIL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/launcher/wildcard.c	Thu Dec 02 05:45:54 2010 -0800
@@ -0,0 +1,494 @@
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * Class-Path Wildcards
+ *
+ * The syntax for wildcards is a single asterisk. The class path
+ * foo/"*", e.g., loads all jar files in the directory named foo.
+ * (This requires careful quotation when used in shell scripts.)
+ *
+ * Only files whose names end in .jar or .JAR are matched.
+ * Files whose names end in .zip, or which have a particular
+ * magic number, regardless of filename extension, are not
+ * matched.
+ *
+ * Files are considered regardless of whether or not they are
+ * "hidden" in the UNIX sense, i.e., have names beginning with '.'.
+ *
+ * A wildcard only matches jar files, not class files in the same
+ * directory.  If you want to load both class files and jar files from
+ * a single directory foo then you can say foo:foo/"*", or foo/"*":foo
+ * if you want the jar files to take precedence.
+ *
+ * Subdirectories are not searched recursively, i.e., foo/"*" only
+ * looks for jar files in foo, not in foo/bar, foo/baz, etc.
+ *
+ * Expansion of wildcards is done early, prior to the invocation of a
+ * program's main method, rather than late, during the class-loading
+ * process itself.  Each element of the input class path containing a
+ * wildcard is replaced by the (possibly empty) sequence of elements
+ * generated by enumerating the jar files in the named directory.  If
+ * the directory foo contains a.jar, b.jar, and c.jar,
+ * e.g., then the class path foo/"*" is expanded into
+ * foo/a.jar:foo/b.jar:foo/c.jar, and that string would be the value
+ * of the system property java.class.path.
+ *
+ * The order in which the jar files in a directory are enumerated in
+ * the expanded class path is not specified and may vary from platform
+ * to platform and even from moment to moment on the same machine.  A
+ * well-constructed application should not depend upon any particular
+ * order.  If a specific order is required then the jar files can be
+ * enumerated explicitly in the class path.
+ *
+ * The CLASSPATH environment variable is not treated any differently
+ * from the -classpath (equiv. -cp) command-line option,
+ * i.e. wildcards are honored in all these cases.
+ *
+ * Class-path wildcards are not honored in the Class-Path jar-manifest
+ * header.
+ *
+ * Class-path wildcards are honored not only by the Java launcher but
+ * also by most other command-line tools that accept class paths, and
+ * in particular by javac and javadoc.
+ *
+ * Class-path wildcards are not honored in any other kind of path, and
+ * especially not in the bootstrap class path, which is a mere
+ * artifact of our implementation and not something that developers
+ * should use.
+ *
+ * Classpath wildcards are only expanded in the Java launcher code,
+ * supporting the use of wildcards on the command line and in the
+ * CLASSPATH environment variable.  We do not support the use of
+ * wildcards by applications that embed the JVM.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include "java.h"       /* Strictly for PATH_SEPARATOR/FILE_SEPARATOR */
+#include "jli_util.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else /* Unix */
+#include <unistd.h>
+#include <dirent.h>
+#endif /* Unix */
+
+static int
+exists(const char* filename)
+{
+#ifdef _WIN32
+    return _access(filename, 0) == 0;
+#else
+    return access(filename, F_OK) == 0;
+#endif
+}
+
+#define NEW_(TYPE) ((TYPE) JLI_MemAlloc(sizeof(struct TYPE##_)))
+
+/*
+ * Wildcard directory iteration.
+ * WildcardIterator_for(wildcard) returns an iterator.
+ * Each call to that iterator's next() method returns the basename
+ * of an entry in the wildcard's directory.  The basename's memory
+ * belongs to the iterator.  The caller is responsible for prepending
+ * the directory name and file separator, if necessary.
+ * When done with the iterator, call the close method to clean up.
+ */
+typedef struct WildcardIterator_* WildcardIterator;
+
+#ifdef _WIN32
+struct WildcardIterator_
+{
+    HANDLE handle;
+    char *firstFile; /* Stupid FindFirstFile...FindNextFile */
+};
+
+static WildcardIterator
+WildcardIterator_for(const char *wildcard)
+{
+    WIN32_FIND_DATA find_data;
+    WildcardIterator it = NEW_(WildcardIterator);
+    HANDLE handle = FindFirstFile(wildcard, &find_data);
+    if (handle == INVALID_HANDLE_VALUE)
+        return NULL;
+    it->handle = handle;
+    it->firstFile = find_data.cFileName;
+    return it;
+}
+
+static char *
+WildcardIterator_next(WildcardIterator it)
+{
+    WIN32_FIND_DATA find_data;
+    if (it->firstFile != NULL) {
+        char *firstFile = it->firstFile;
+        it->firstFile = NULL;
+        return firstFile;
+    }
+    return FindNextFile(it->handle, &find_data)
+        ? find_data.cFileName : NULL;
+}
+
+static void
+WildcardIterator_close(WildcardIterator it)
+{
+    if (it) {
+        FindClose(it->handle);
+        JLI_MemFree(it->firstFile);
+        JLI_MemFree(it);
+    }
+}
+
+#else /* Unix */
+struct WildcardIterator_
+{
+    DIR *dir;
+};
+
+static WildcardIterator
+WildcardIterator_for(const char *wildcard)
+{
+    DIR *dir;
+    int wildlen = strlen(wildcard);
+    if (wildlen < 2) {
+        dir = opendir(".");
+    } else {
+        char *dirname = JLI_StringDup(wildcard);
+        dirname[wildlen - 1] = '\0';
+        dir = opendir(dirname);
+        JLI_MemFree(dirname);
+    }
+    if (dir == NULL)
+        return NULL;
+    else {
+        WildcardIterator it = NEW_(WildcardIterator);
+        it->dir = dir;
+        return it;
+    }
+}
+
+static char *
+WildcardIterator_next(WildcardIterator it)
+{
+    struct dirent* dirp = readdir(it->dir);
+    return dirp ? dirp->d_name : NULL;
+}
+
+static void
+WildcardIterator_close(WildcardIterator it)
+{
+    if (it) {
+        closedir(it->dir);
+        JLI_MemFree(it);
+    }
+}
+#endif /* Unix */
+
+static int
+equal(const char *s1, const char *s2)
+{
+    return strcmp(s1, s2) == 0;
+}
+
+/*
+ * FileList ADT - a dynamic list of C filenames
+ */
+struct FileList_
+{
+    char **files;
+    int size;
+    int capacity;
+};
+typedef struct FileList_ *FileList;
+
+static FileList
+FileList_new(int capacity)
+{
+    FileList fl = NEW_(FileList);
+    fl->capacity = capacity;
+    fl->files = (char **) JLI_MemAlloc(capacity * sizeof(fl->files[0]));
+    fl->size = 0;
+    return fl;
+}
+
+#ifdef DEBUG_WILDCARD
+static void
+FileList_print(FileList fl)
+{
+    int i;
+    putchar('[');
+    for (i = 0; i < fl->size; i++) {
+        if (i > 0) printf(", ");
+        printf("\"%s\"",fl->files[i]);
+    }
+    putchar(']');
+}
+#endif
+
+static void
+FileList_free(FileList fl)
+{
+    if (fl) {
+        if (fl->files) {
+            int i;
+            for (i = 0; i < fl->size; i++)
+                JLI_MemFree(fl->files[i]);
+            JLI_MemFree(fl->files);
+        }
+        JLI_MemFree(fl);
+    }
+}
+
+static void
+FileList_ensureCapacity(FileList fl, int capacity)
+{
+    if (fl->capacity < capacity) {
+        while (fl->capacity < capacity)
+            fl->capacity *= 2;
+        fl->files = JLI_MemRealloc(fl->files,
+                               fl->capacity * sizeof(fl->files[0]));
+    }
+}
+
+static void
+FileList_add(FileList fl, char *file)
+{
+    FileList_ensureCapacity(fl, fl->size+1);
+    fl->files[fl->size++] = file;
+}
+
+static void
+FileList_addSubstring(FileList fl, const char *beg, int len)
+{
+    char *filename = (char *) JLI_MemAlloc(len+1);
+    memcpy(filename, beg, len);
+    filename[len] = '\0';
+    FileList_ensureCapacity(fl, fl->size+1);
+    fl->files[fl->size++] = filename;
+}
+
+static char *
+FileList_join(FileList fl, char sep)
+{
+    int i;
+    int size;
+    char *path;
+    char *p;
+    for (i = 0, size = 1; i < fl->size; i++)
+        size += strlen(fl->files[i]) + 1;
+
+    path = JLI_MemAlloc(size);
+
+    for (i = 0, p = path; i < fl->size; i++) {
+        int len = strlen(fl->files[i]);
+        if (i > 0) *p++ = sep;
+        memcpy(p, fl->files[i], len);
+        p += len;
+    }
+    *p = '\0';
+
+    return path;
+}
+
+static FileList
+FileList_split(const char *path, char sep)
+{
+    const char *p, *q;
+    int len = strlen(path);
+    int count;
+    FileList fl;
+    for (count = 1, p = path; p < path + len; p++)
+        count += (*p == sep);
+    fl = FileList_new(count);
+    for (p = path;;) {
+        for (q = p; q <= path + len; q++) {
+            if (*q == sep || *q == '\0') {
+                FileList_addSubstring(fl, p, q - p);
+                if (*q == '\0')
+                    return fl;
+                p = q + 1;
+            }
+        }
+    }
+}
+
+static int
+isJarFileName(const char *filename)
+{
+    int len = strlen(filename);
+    return (len >= 4) &&
+        (filename[len - 4] == '.') &&
+        (equal(filename + len - 3, "jar") ||
+         equal(filename + len - 3, "JAR")) &&
+        /* Paranoia: Maybe filename is "DIR:foo.jar" */
+        (strchr(filename, PATH_SEPARATOR) == NULL);
+}
+
+static char *
+wildcardConcat(const char *wildcard, const char *basename)
+{
+    int wildlen = strlen(wildcard);
+    int baselen = strlen(basename);
+    char *filename = (char *) JLI_MemAlloc(wildlen + baselen);
+    /* Replace the trailing '*' with basename */
+    memcpy(filename, wildcard, wildlen-1);
+    memcpy(filename+wildlen-1, basename, baselen+1);
+    return filename;
+}
+
+static FileList
+wildcardFileList(const char *wildcard)
+{
+    const char *basename;
+    FileList fl = FileList_new(16);
+    WildcardIterator it = WildcardIterator_for(wildcard);
+    if (it == NULL)
+        return NULL;
+    while ((basename = WildcardIterator_next(it)) != NULL)
+        if (isJarFileName(basename))
+            FileList_add(fl, wildcardConcat(wildcard, basename));
+    WildcardIterator_close(it);
+    return fl;
+}
+
+static int
+isWildcard(const char *filename)
+{
+    int len = strlen(filename);
+    return (len > 0) &&
+        (filename[len - 1] == '*') &&
+        (len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) &&
+        (! exists(filename));
+}
+
+static void
+FileList_expandWildcards(FileList fl)
+{
+    int i, j;
+    for (i = 0; i < fl->size; i++) {
+        if (isWildcard(fl->files[i])) {
+            FileList expanded = wildcardFileList(fl->files[i]);
+            if (expanded != NULL && expanded->size > 0) {
+                JLI_MemFree(fl->files[i]);
+                FileList_ensureCapacity(fl, fl->size + expanded->size);
+                for (j = fl->size - 1; j >= i+1; j--)
+                    fl->files[j+expanded->size-1] = fl->files[j];
+                for (j = 0; j < expanded->size; j++)
+                    fl->files[i+j] = expanded->files[j];
+                i += expanded->size - 1;
+                fl->size += expanded->size - 1;
+                /* fl expropriates expanded's elements. */
+                expanded->size = 0;
+            }
+            FileList_free(expanded);
+        }
+    }
+}
+
+const char *
+JLI_WildcardExpandClasspath(const char *classpath)
+{
+    char *expanded;
+    FileList fl;
+
+    if (strchr(classpath, '*') == NULL)
+        return classpath;
+    fl = FileList_split(classpath, PATH_SEPARATOR);
+    FileList_expandWildcards(fl);
+    expanded = FileList_join(fl, PATH_SEPARATOR);
+    FileList_free(fl);
+    if (getenv("_JAVA_LAUNCHER_DEBUG") != 0)
+        printf("Expanded wildcards:\n"
+               "    before: \"%s\"\n"
+               "    after : \"%s\"\n",
+               classpath, expanded);
+    return expanded;
+}
+
+#ifdef DEBUG_WILDCARD
+static void
+wildcardExpandArgv(const char ***argv)
+{
+    int i;
+    for (i = 0; (*argv)[i]; i++) {
+        if (equal((*argv)[i], "-cp") ||
+            equal((*argv)[i], "-classpath")) {
+            i++;
+            (*argv)[i] = wildcardExpandClasspath((*argv)[i]);
+        }
+    }
+}
+
+static void
+debugPrintArgv(char *argv[])
+{
+    int i;
+    putchar('[');
+    for (i = 0; argv[i]; i++) {
+        if (i > 0) printf(", ");
+        printf("\"%s\"", argv[i]);
+    }
+    printf("]\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+    argv[0] = "java";
+    wildcardExpandArgv((const char***)&argv);
+    debugPrintArgv(argv);
+    /* execvp("java", argv); */
+    return 0;
+}
+#endif /* DEBUG_WILDCARD */
+
+/* Cute little perl prototype implementation....
+
+my $sep = ($^O =~ /^(Windows|cygwin)/) ? ";" : ":";
+
+sub expand($) {
+  opendir DIR, $_[0] or return $_[0];
+  join $sep, map {"$_[0]/$_"} grep {/\.(jar|JAR)$/} readdir DIR;
+}
+
+sub munge($) {
+  join $sep,
+    map {(! -r $_ and s/[\/\\]+\*$//) ? expand $_ : $_} split $sep, $_[0];
+}
+
+for (my $i = 0; $i < @ARGV - 1; $i++) {
+  $ARGV[$i+1] = munge $ARGV[$i+1] if $ARGV[$i] =~ /^-c(p|lasspath)$/;
+}
+
+$ENV{CLASSPATH} = munge $ENV{CLASSPATH} if exists $ENV{CLASSPATH};
+@ARGV = ("java", @ARGV);
+print "@ARGV\n";
+exec @ARGV;
+
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/tools/launcher/wildcard.h	Thu Dec 02 05:45:54 2010 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef WILDCARD_H_
+#define WILDCARD_H_
+
+#ifdef EXPAND_CLASSPATH_WILDCARDS
+const char *JLI_WildcardExpandClasspath(const char *classpath);
+#else
+#define JLI_WildcardExpandClasspath(s) (s)
+#endif
+
+#endif /* include guard */
--- a/hotspot/src/share/vm/prims/jvm.h	Thu Dec 02 20:01:47 2010 +0100
+++ b/hotspot/src/share/vm/prims/jvm.h	Thu Dec 02 05:45:54 2010 -0800
@@ -27,7 +27,6 @@
 
 #include "prims/jni.h"
 #include "runtime/reflectionCompat.hpp"
-#include "utilities/globalDefinitions.hpp"
 #ifdef TARGET_OS_FAMILY_linux
 # include "jvm_linux.h"
 #endif