java_md.c revision 2746
2581N/A * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 0N/A * Returns the arch path, to get the current arch use the 0N/A * macro GetArch, nbits here is ignored for now. 0N/A /* Find out where the JRE is that we will be using. */ 2733N/A /* Do this before we read jvm.cfg and after jrepath is initialized */ 0N/A /* Find the specified JVM type */ 0N/A /* If we got here, jvmpath has been correctly initialized. */ 1365N/A * The Microsoft C Runtime Library needs to be loaded first. A copy is 1365N/A * assumed to be present in the "JRE path" directory. If it is not found 1365N/A * there (or "JRE path" fails to resolve), skip the explicit load and let 1365N/A * nature take its course, which is likely to be a failure to execute. 2324N/A * This is clearly completely specific to the exact compiler version 2324N/A * which isn't very nice, but its hardly the only place. 2324N/A * No attempt to look for compiler versions in between 2003 and 2010 2324N/A * as we aren't supporting building with those. 1365N/A * The preJVMStart is a function in the jkernel.dll, which 1365N/A * performs the final step of synthesizing back the decomposed 1365N/A * modules (partial install) to the full JRE. Any tool which 1365N/A * uses the JRE must peform this step to ensure the complete synthesis. 1365N/A * The EnsureJreInstallation function calls preJVMStart based on 1365N/A * the conditions outlined below, noting that the operation 1365N/A * will fail silently if any of conditions are not met. 1365N/A * NOTE: this call must be made before jvm.dll is loaded, or jvm.cfg 1365N/A * is read, since jvm.cfg will be modified by the preJVMStart. 1365N/A * 1. Are we on a supported platform. 1365N/A * 2. Find the location of the JRE or the Kernel JRE. 1365N/A * 4. check jkernel.dll and invoke the entry-point 2581N/A /* Make sure the jrepath contains something */ 1365N/A /* 32 bit windows only please */ 1365N/A /* Does our bundle directory exist ? */ 1365N/A /* Does our jkernel dll exist ? */ 1365N/A /* The Microsoft C Runtime Library needs to be loaded first. */ 1365N/A /* Get the function address */ 0N/A * Find path to JRE based on .exe's location or registry settings. 0N/A /* Is JRE co-located with the application? */ 0N/A /* Does this app ship a private JRE in <apphome>\jre directory? */ 0N/A /* Look for a public JRE on this machine. */ 0N/A * Given a JRE location and a JVM type, construct what the name the 0N/A * JVM shared library will be. Return true, if such a library 0N/A * exists, false otherwise. 0N/A * Load a jvm from "jvmpath" and initialize the invocation functions. 0N/A * The Microsoft C Runtime Library needs to be loaded first. A copy is 0N/A * assumed to be present in the "JRE path" directory. If it is not found 0N/A * there (or "JRE path" fails to resolve), skip the explicit load and let 0N/A * nature take its course, which is likely to be a failure to execute. 0N/A /* Load the Java VM DLL */ 0N/A /* Now get the function addresses */ 0N/A * If app is "c:\foo\bin\javac", then put "c:\foo" into buf. 0N/A /* This happens if the application is in a drive root, and 0N/A * there is no bin directory. */ 0N/A *
cp =
'\0';
/* remove the bin\ part */ 0N/A * Helpers to look in the registry for a public JRE. 0N/A /* Same for 1.5.0, 1.5.1, 1.5.2 etc. */ 0N/A#
define JRE_KEY "Software\\JavaSoft\\Java Runtime Environment" 0N/A * Note: There is a very similar implementation of the following 0N/A * registry reading code in the Windows java control panel (javacp.cpl). 0N/A * If there are bugs here, a similar bug probably exists there. Hence, 0N/A * changes here require inspection there. 0N/A /* Find the current version of the JRE */ 0N/A /* Find directory where the current version is installed. */ 0N/A printf(
"Warning: Can't read MicroVersion\n");
0N/A * Support for doing cheap, accurate interval timing. 0N/A /* get the length of the string we need */ 517N/A * Just like JLI_ReportErrorMessage, except that it concatenates the system 0N/A * error message if any, its upto the calling routine to correctly 0N/A * format the separation of the messages. 0N/A if (n >
2) {
/* Drop final CR, LF */ 0N/A }
else {
/* C runtime error that has no corresponding DOS error code */ 0N/A /* get the length of the string we need */ 0N/A * This code should be replaced by code which opens a window with 0N/A * the exception detail message, for now atleast put a dialog up. 0N/A * Determine if there is an acceptable JRE in the registry directory top_key. 0N/A * Upon locating the "best" one, return a fully qualified path to it. 0N/A * "Best" is defined as the most advanced JRE meeting the constraints 0N/A * contained in the manifest_info. If no JRE in this directory meets the 0N/A * constraints, return NULL. 0N/A * It doesn't matter if we get an error reading the registry, or we just 0N/A * don't find anything interesting in the directory. We just return NULL 0N/A * searching for the best available version. 0N/A * Extract "JavaHome" from the "best" registry directory and return 0N/A * that path. If no appropriate version was located, or there is an 0N/A * error in extracting the "JavaHome" string, return null. 0N/A * This is the global entry point. It examines the host for the optimal 0N/A * JRE to be used by scanning a set of registry entries. This set of entries 0N/A * is hardwired on Windows as "Software\JavaSoft\Java Runtime Environment" 0N/A * under the set of roots "{ HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }". 0N/A * This routine simply opens each of these registry directories before passing 0N/A * control onto ProcessDir(). 0N/A * Local helper routine to isolate a single token (option or argument) 0N/A * from the command line. 0N/A * This routine accepts a pointer to a character pointer. The first 0N/A * token (as defined by MSDN command-line argument syntax) is isolated 0N/A * Upon return, the input character pointer pointed to by the parameter s 0N/A * is updated to point to the remainding, unscanned, portion of the string, 0N/A * or to a null character if the entire string has been consummed. 0N/A * This function returns a pointer to a null-terminated string which 0N/A * contains the isolated first token, or to the null character if no 0N/A * token could be isolated. 0N/A * Note the side effect of modifying the input string s by the insertion 0N/A * of a null character, making it two strings. 0N/A * See "Parsing C Command-Line Arguments" in the MSDN Library for the 0N/A * parsing rule details. The rule summary from that specification is: 0N/A * * Arguments are delimited by white space, which is either a space or a tab. 0N/A * * A string surrounded by double quotation marks is interpreted as a single 0N/A * argument, regardless of white space contained within. A quoted string can 0N/A * be embedded in an argument. Note that the caret (^) is not recognized as 0N/A * an escape character or delimiter. 0N/A * * A double quotation mark preceded by a backslash, \", is interpreted as a 0N/A * literal double quotation mark ("). 0N/A * * Backslashes are interpreted literally, unless they immediately precede a 0N/A * double quotation mark. 0N/A * * If an even number of backslashes is followed by a double quotation mark, 0N/A * then one backslash (\) is placed in the argv array for every pair of 0N/A * backslashes (\\), and the double quotation mark (") is interpreted as a 0N/A * * If an odd number of backslashes is followed by a double quotation mark, 0N/A * then one backslash (\) is placed in the argv array for every pair of 0N/A * backslashes (\\) and the double quotation mark is interpreted as an 0N/A * escape sequence by the remaining backslash, causing a literal double 0N/A * quotation mark (") to be placed in argv. 0N/A * Strip leading whitespace, which MSDN defines as only space or tab. 0N/A * (Hence, no locale specific "isspace" here.) 0N/A while (*p != (
char)0 && (*p ==
' ' || *p ==
'\t'))
0N/A head = p;
/* Save the start of the token to return */ 0N/A * Isolate a token from the command line. 0N/A while (*p != (
char)0 && (
inquote || !(*p ==
' ' || *p ==
'\t'))) {
0N/A if (*p ==
'\\' && *(p+
1) ==
'"' &&
slashes %
2 == 0)
0N/A * If the token isolated isn't already terminated in a "char zero", 0N/A * then replace the whitespace character with one and move to the 0N/A * Update the parameter to point to the head of the remaining string 0N/A * reflecting the command line and return a pointer to the leading 0N/A * token which was isolated from the command line. 0N/A * Local helper routine to return a string equivalent to the input string 0N/A * s, but with quotes removed so the result is a string as would be found 0N/A * in argv[]. The returned string should be freed by a call to JLI_MemFree(). 0N/A * The rules for quoting (and escaped quotes) are: 0N/A * 1 A double quotation mark preceded by a backslash, \", is interpreted as a 0N/A * literal double quotation mark ("). 0N/A * 2 Backslashes are interpreted literally, unless they immediately precede a 0N/A * double quotation mark. 0N/A * 3 If an even number of backslashes is followed by a double quotation mark, 0N/A * then one backslash (\) is placed in the argv array for every pair of 0N/A * backslashes (\\), and the double quotation mark (") is interpreted as a 0N/A * 4 If an odd number of backslashes is followed by a double quotation mark, 0N/A * then one backslash (\) is placed in the argv array for every pair of 0N/A * backslashes (\\) and the double quotation mark is interpreted as an 0N/A * escape sequence by the remaining backslash, causing a literal double 0N/A * quotation mark (") to be placed in argv. 0N/A const char *p = s;
/* Pointer to the tail of the original string */ 0N/A char *
pun =
un;
/* Pointer to the tail of the unquoted string */ 0N/A while (*p !=
'\0') {
0N/A }
else if (*p ==
'\\') {
0N/A }
while (*p ==
'\\' && p < q);
0N/A * Given a path to a jre to execute, this routine checks if this process 0N/A * is indeed that jre. If not, it exec's that jre. 0N/A * We want to actually check the paths rather than just the version string 0N/A * built into the executable, so that given version specification will yield 0N/A * the exact same Java environment, regardless of the version of the arbitrary 0N/A * launcher we start with. 0N/A * Resolve the real path to the currently running launcher. 0N/A * If the path to the selected JRE directory is a match to the initial 0N/A * portion of the path to the currently executing JRE, we have a winner! 0N/A * If so, just return. 0N/A return;
/* I am the droid you were looking for */ 0N/A * If this isn't the selected version, exec the selected version. 0N/A * Although Windows has an execv() entrypoint, it doesn't actually 0N/A * overlay a process: it can only create a new process and terminate 0N/A * the old process. Therefore, any processes waiting on the initial 0N/A * process wake up and they shouldn't. Hence, a chain of pseudo-zombie 0N/A * processes must be retained to maintain the proper wait semantics. 0N/A * Fortunately the image size of the launcher isn't too large at this 0N/A * If it weren't for this semantic flaw, the code below would be ... 0N/A * execv(path, argv); 517N/A * JLI_ReportErrorMessage("Error: Exec of %s failed\n", path); 0N/A * The incorrect exec semantics could be addressed by: 0N/A * exit((int)spawnv(_P_WAIT, path, argv)); 0N/A * Unfortunately, a bug in Windows spawn/exec impementation prevents 0N/A * this from completely working. All the Windows POSIX process creation 0N/A * interfaces are implemented as wrappers around the native Windows 0N/A * function CreateProcess(). CreateProcess() takes a single string 0N/A * to specify command line options and arguments, so the POSIX routine 0N/A * wrappers build a single string from the argv[] array and in the 0N/A * process, any quoting information is lost. 0N/A * The solution to this to get the original command line, to process it 0N/A * to remove the new multiple JRE options (if any) as was done for argv 0N/A * in the common SelectVersion() routine and finally to pass it directly 0N/A * to the native CreateProcess() Windows process control interface. 0N/A * The following code block gets and processes the original command 0N/A * line, replacing the argv[0] equivalent in the command line with 0N/A * the path to the new executable and removing the appropriate 0N/A * Multiple JRE support options. Note that similar logic exists 0N/A * in the platform independent SelectVersion routine, but is 0N/A * replicated here due to the syntax of CreateProcess(). 0N/A * The magic "+ 4" characters added to the command line length are 0N/A * 2 possible quotes around the path (argv[0]), a space after the 0N/A * path and a terminating null character. 0N/A while (*
np != (
char)0) {
/* While more command-line */ 0N/A if (*p != (
char)0) {
/* If a token was isolated */ 0N/A if (*p != (
char)0)
/* If a token was isolated */ 0N/A }
else {
/* End of options */ 0N/A * The following code is modeled after a model presented in the 0N/A * Microsoft Technical Article "Moving Unix Applications to 0N/A * Windows NT" (March 6, 1994) and "Creating Processes" on MSDN 0N/A * (Februrary 2005). It approximates UNIX spawn semantics with 0N/A * the parent waiting for termination of the child. 0N/A * Wrapper for platform dependent unsetenv function. 0N/A/* --- Splash Screen shared library support --- */ 0N/A * Block current thread and continue execution in a new thread 0N/A * STACK_SIZE_PARAM_IS_A_RESERVATION is what we want, but it's not 0N/A * supported on older version of Windows. Try first with the flag; and 0N/A * if that fails try again without the flag. See MSDN document or HotSpot 647N/A/* Unix only, empty on windows. */ 647N/A * The implementation for finding classes from the bootstrap 647N/A /* need to use the demangled entry point */ 1645N/A "JVM_FindClassFromBootLoader");
16N/A * Required for javaw mode MessageBox output as well as for 16N/A * HotSpot -XX:+ShowMessageBoxOnError in java mode, an empty 16N/A * flag field is sufficient to perform the basic UI initialization.