2362N/A * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. 2180N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2180N/A * This code is free software; you can redistribute it and/or modify it 2180N/A * under the terms of the GNU General Public License version 2 only, as 2180N/A * published by the Free Software Foundation. Oracle designates this 2180N/A * particular file as subject to the "Classpath" exception as provided 2180N/A * by Oracle in the LICENSE file that accompanied this code. 2180N/A * This code is distributed in the hope that it will be useful, but WITHOUT 2180N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2180N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2180N/A * version 2 for more details (a copy is included in the LICENSE file that 2180N/A * You should have received a copy of the GNU General Public License version 2180N/A * 2 along with this work; if not, write to the Free Software Foundation, 2362N/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 2180N/A/* help jettison the LD_LIBRARY_PATH settings in the future */ 2180N/A * If a processor / os combination has the ability to run binaries of 2180N/A * two data models and cohabitation of jre/jdk bits with both data 2180N/A * models is supported, then DUAL_MODE is defined. When DUAL_MODE is 2180N/A * defined, the architecture names for the narrow and wide version of 2180N/A * the architecture are defined in LIBARCH64NAME and LIBARCH32NAME. 2180N/A#
error "The macro LIBARCH32NAME was not defined on the compile line" 2180N/A#
error "The macro LIBARCH64NAME was not defined on the compile line" 2180N/A * Flowchart of launcher execs and options processing on unix 2180N/A * The selection of the proper vm shared library to open depends on 2180N/A * several classes of command line options, including vm "flavor" 2180N/A * options (-client, -server) and the data model options, -d32 and 2180N/A * -d64, as well as a version specification which may have come from 2180N/A * the command line or from the manifest of an executable jar file. 2180N/A * The vm selection options are not passed to the running 2180N/A * virtual machine; they must be screened out by the launcher. 2180N/A * The version specification (if any) is processed first by the 2180N/A * platform independent routine SelectVersion. This may result in 2180N/A * the exec of the specified launcher version. 2180N/A * Previously the launcher modified the LD_LIBRARY_PATH appropriately for the 2180N/A * desired data model path, regardless if data models matched or not. The 2180N/A * launcher subsequently exec'ed the desired executable, in order to make the 2180N/A * LD_LIBRARY_PATH path available, for the runtime linker. 2180N/A * Now, in most cases,the launcher will dlopen the target libjvm.so. All 2180N/A * required libraries are loaded by the runtime linker, using the 2180N/A * $RPATH/$ORIGIN baked into the shared libraries at compile time. Therefore, 2180N/A * in most cases, the launcher will only exec, if the data models are 2180N/A * mismatched, and will not set any environment variables, regardless of the 2180N/A * However, if the environment contains a LD_LIBRARY_PATH, this will cause the 2180N/A * launcher to inspect the LD_LIBRARY_PATH. The launcher will check 2180N/A * a. if the LD_LIBRARY_PATH's first component is the the path to the desired 2180N/A * If case b is true, then the launcher will set the LD_LIBRARY_PATH to the 2180N/A * desired JRE and reexec, in order to propagate the environment. * (selects the JRE version, note: not data model) * CreateExecutionEnvironment * (determines desired data model) * Have Desired Model ? --> NO --> Is Dual-Mode ? --> NO --> Exit(with error) * | (removes -client, -server etc.) * CheckJvmType RequiresSetenv * (removes -client, -server, etc.) * (Prepare to pass args to vm) * (removes -d32 and -d64 if any, * processes version options, * creates argument list for vm, * and friends set ? --> NO --> Have Desired Model ? NO --> Re-exec --> Main * Path is desired JRE ? YES --> Have Desired Model ? NO --> Re-exec --> Main * jvm paths ? --> NO --> Have Desired Model ? NO --> Re-exec --> Main * in any of them ? --> NO --> Have Desired Model ? NO --> Re-exec --> Main * Set the LD_LIBRARY_PATH /* Store the name of the executable once computed */ * execname accessor from other parts of platform dependent logic * contains a lib/$LIBARCH/{server,client}/libjvm.so ? /* to optimize for time, test if any of our usual suspects are present. */ * we have a suspicious path component, check if it contains a libjvm.so * Test whether the environment variable needs to be set, see flowchart. char *p;
/* a utility pointer */ ?
getenv(
"LD_LIBRARY_PATH_32")
:
getenv(
"LD_LIBRARY_PATH_64");
/* no environment variable is a good environment variable */ * 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, here and further downstream. Therefore, if we are running sgid or * suid, this function's setting of LD_LIBRARY_PATH will be ineffective and * we should case a return from the calling function. Getting the right * libraries will be handled by the RPATH. In reality, this check is * redundant, as the previous check for a non-null LD_LIBRARY_PATH will * return back to the calling function forthwith, it is left here to safe * guard against any changes, in the glibc's existing security policy. * Prevent recursions. Since LD_LIBRARY_PATH is the one which will be set by * previous versions of the JRE, thus it is the only path that matters here. * So we check to see if the desired JRE is set. /* scrutinize all the paths further */ #
endif /* SETENV_REQUIRED */ * 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 /* Check data model flags, and exec process, if needed */ char *
arch = (
char *)
GetArch();
/* like sparc or sparcv9 */ asked for? Current model is fine unless another model char *
runpath =
NULL;
/* existing effective LD_LIBRARY_PATH setting */ char*
newpath =
NULL;
/* path on new LD_LIBRARY_PATH */ char*
dmpath =
NULL;
/* data model specific LD_LIBRARY_PATH, #
endif /* SETENV_REQUIRED */ * 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 */ /* scan for data model arguments and remove from argument list; last occurrence determines desired data model */ for (i=
1; i <
argc; i++) {
if (
argv[i][0] !=
'-')
continue;
if (
argv[i][0] !=
'-') { i++;
break; }
/* copy rest of args [i .. argc) */ * newargv has all proper arguments here /* If the data model is not changing, it is an error if the jvmpath does not exist */ /* Find out where the JRE is that we will be using. */ /* Find the specified JVM type */ * we seem to have everything we need, so without further ado * we return back, otherwise proceed to set the environment. #
endif /* SETENV_REQUIRED */ }
else {
/* do the same speculatively or exit */ /* Find out where the JRE is that we will be using. */ /* give up and let other code report error message */ * Read in jvm.cfg for target data model and process vm /* give up and let other code report error message */ /* exec child can do error checking on the existence of the path */ #
endif /* SETENV_REQUIRED */ * We will set the LD_LIBRARY_PATH as follows: * o $JVMPATH (directory portion only) * o $JRE/../lib/$LIBARCHNAME * followed by the user's previous effective LD_LIBRARY_PATH, if * Starting in Solaris 7, ld.so.1 supports three LD_LIBRARY_PATH * 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 * 3. LD_LIBRARY_PATH_32 -- overrides and replaces LD_LIBRARY_PATH * 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. exit(
1);
/* unknown value in wanted */ * If dmpath is NULL, the relevant data model specific variable is * not set and normal LD_LIBRARY_PATH should be used. #
else /* ! __solaris__ */ * If not on Solaris, assume only a single LD_LIBRARY_PATH /* runpath contains current effective LD_LIBRARY_PATH setting */ * Create desired LD_LIBRARY_PATH value for target data model. /* remove the name of the .so from the JVM path */ * Check to make sure that the prefix of the current path is the * desired environment variable setting, though the RequiresSetenv * checks if the desired runpath exists, this logic does a more && (
dmpath ==
NULL)
/* data model specific variables not set */ * 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. exit(
1);
/* problem allocating memory; LD_LIBRARY_PATH not set * 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. * If dmpath is not NULL, remove the data model specific string * in the environment for the exec'ed child. (
void)
UnsetEnv((
wanted ==
32) ?
"LD_LIBRARY_PATH_32" :
"LD_LIBRARY_PATH_64");
#
endif /* SETENV_REQUIRED */ * 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. * the bits are assumed to be in "olddir/../execname". For example, * for Solaris SPARC and Linux amd64, respectively. #
else /* !SETENV_REQUIRED */#
endif /* SETENV_REQUIRED */ * On Solaris VM choosing is done by the launcher (java.c), * bitsWanted is used by MacOSX, on Solaris and Linux this. * Find path to JRE based on .exe's location or registry settings. /* Is JRE co-located with the application? */ /* Does the app ship a private JRE in <apphome>/jre directory? */ * 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 char buf[
257];
/* recommended buffer size from sysinfo man * 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. buf[
len] =
'\0';
/* readlink doesn't nul terminate */ #
else /* !__solaris__ && !__linux__ *//* --- Splash Screen shared library support --- */ * Block current thread and continue execution in a new thread /* See below. Continue in current thread if thr_create() failed */ #
else /* ! __solaris__ */ * 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.. /* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */ // stubbed out for windows and *nixes. // stubbed out for windows and *nixes. * on unix, we return a false to indicate this option is not applicable