mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8340114: Remove outdated SelectVersion() function from the launcher and update the code comments explaining the code flow
Reviewed-by: dholmes, alanb
This commit is contained in:
parent
c8ae848049
commit
40cde003e8
8 changed files with 260 additions and 642 deletions
|
@ -60,115 +60,79 @@ struct NSAppArgs {
|
|||
#define LD_LIBRARY_PATH "DYLD_FALLBACK_LIBRARY_PATH"
|
||||
|
||||
/*
|
||||
* 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. MacOSX is a hybrid
|
||||
* system in that, the universal library can contain all types of libraries
|
||||
* 32/64 and client/server, thus the spawn is capable of linking with the
|
||||
* appropriate library as requested.
|
||||
* Following is the high level flow of the launcher
|
||||
* code residing in the common java.c and this
|
||||
* macosx specific java_md_macosx file:
|
||||
*
|
||||
* Notes:
|
||||
* 1. VM. DUAL_MODE is disabled, and not supported, however, it is left here in
|
||||
* for experimentation and perhaps enable it in the future.
|
||||
* 2. At the time of this writing, the universal library contains only
|
||||
* a server 64-bit server JVM.
|
||||
* 3. "-client" command line option is supported merely as a command line flag,
|
||||
* for, compatibility reasons, however, a server VM will be launched.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Flowchart of launcher execs and options processing on unix
|
||||
* - JLI_Launch function, which is the entry point
|
||||
* to the launcher, calls CreateExecutionEnvironment.
|
||||
*
|
||||
* 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.
|
||||
* - CreateExecutionEnvironment does the following
|
||||
* (not necessarily in this order):
|
||||
* - determines the relevant JVM type that needs
|
||||
* to be ultimately created
|
||||
* - determines the path and asserts the presence
|
||||
* of libjava and relevant libjvm library
|
||||
* - removes any JVM selection options from the
|
||||
* arguments that were passed to 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.
|
||||
* - CreateExecutionEnvironment then creates a new
|
||||
* thread, within the same process, to launch the
|
||||
* application's main() Java method and parks the
|
||||
* current thread, on which CreateExecutionEnvironment
|
||||
* was invoked, in Apple's Cocoa event loop. Before
|
||||
* doing so, CreateExecutionEnvironment maintains a
|
||||
* state flag to keep note that a new thread has
|
||||
* been spawned.
|
||||
*
|
||||
* Now, in most cases,the launcher will dlopen the target libjvm.so. All
|
||||
* required libraries are loaded by the runtime linker, using the known paths
|
||||
* baked into the shared libraries at compile time. Therefore,
|
||||
* in most cases, the launcher will only exec, if the data models are
|
||||
* mismatched, and will not set any environment variables, regardless of the
|
||||
* data models.
|
||||
* - The newly created thread (in which the application's
|
||||
* main() method will ultimately run) starts right from
|
||||
* the beginning of the current process' main function,
|
||||
* which effectively means that JLI_Launch is re-invoked
|
||||
* on this new thread and the same above sequence of code
|
||||
* flow repeats again. During this "recursive" call, when
|
||||
* at the point of creating a new thread in
|
||||
* CreateExecutionEnvironment, the CreateExecutionEnvironment
|
||||
* will check for the state flag to see if a new thread
|
||||
* has already been spawned and upon noticing that it
|
||||
* has, it will skip spawning any more threads and will
|
||||
* return back from CreateExecutionEnvironment.
|
||||
*
|
||||
* - The control returns back from CreateExecutionEnvironment
|
||||
* to JLI_Launch, and the thread on which the control
|
||||
* returns is the thread on which the application's main()
|
||||
* Java method will be invoked.
|
||||
*
|
||||
* - JLI_Launch then invokes LoadJavaVM which dlopen()s the
|
||||
* JVM library and asserts the presence of JNI Invocation
|
||||
* Functions "JNI_CreateJavaVM", "JNI_GetDefaultJavaVMInitArgs"
|
||||
* and "JNI_GetCreatedJavaVMs" in that library. It then sets
|
||||
* internal function pointers in the launcher to point to
|
||||
* those functions.
|
||||
*
|
||||
* Main
|
||||
* (incoming argv)
|
||||
* |
|
||||
* \|/
|
||||
* CreateExecutionEnvironment
|
||||
* (determines desired data model)
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* Have Desired Model ? --> NO --> Is Dual-Mode ? --> NO --> Exit(with error)
|
||||
* | |
|
||||
* | |
|
||||
* | \|/
|
||||
* | YES
|
||||
* | |
|
||||
* | |
|
||||
* | \|/
|
||||
* | CheckJvmType
|
||||
* | (removes -client, -server etc.)
|
||||
* | |
|
||||
* | |
|
||||
* \|/ \|/
|
||||
* YES Find the desired executable/library
|
||||
* | |
|
||||
* | |
|
||||
* \|/ \|/
|
||||
* CheckJvmType POINT A
|
||||
* (removes -client, -server, etc.)
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* TranslateDashJArgs...
|
||||
* (Prepare to pass args to vm)
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* ParseArguments
|
||||
* (processes version options,
|
||||
* creates argument list for vm,
|
||||
* etc.)
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* POINT A
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* Path is desired JRE ? YES --> Continue
|
||||
* NO
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* Paths have well known
|
||||
* jvm paths ? --> NO --> Continue
|
||||
* YES
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* Does libjvm.so exist
|
||||
* in any of them ? --> NO --> Continue
|
||||
* YES
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* Re-exec / Spawn
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* Main
|
||||
* - JLI_Launch then translates any -J options by invoking
|
||||
* TranslateApplicationArgs.
|
||||
*
|
||||
* - JLI_Launch then invokes ParseArguments to parse/process
|
||||
* the launcher arguments.
|
||||
*
|
||||
* - JLI_Launch then ultimately calls JVMInit.
|
||||
*
|
||||
* - JVMInit then invokes JavaMain.
|
||||
*
|
||||
* - JavaMain, before launching the application, invokes
|
||||
* PostJVMInit.
|
||||
*
|
||||
* - PostJVMInit invokes ShowSplashScreen which displays
|
||||
* a splash screen for the application, if applicable.
|
||||
*
|
||||
* - Control then returns back from PostJVMInit into
|
||||
* JavaMain, which then loads the application's main
|
||||
* class and invokes the relevant main() Java method.
|
||||
*
|
||||
* - JavaMain then returns back an integer result which
|
||||
* then gets propagated as a return value all the way
|
||||
* out of the JLI_Launch function.
|
||||
*/
|
||||
|
||||
/* Store the name of the executable once computed */
|
||||
|
|
|
@ -103,9 +103,6 @@
|
|||
#define JRE_ERROR12 "Error: Exec of %s failed"
|
||||
#define JRE_ERROR13 "Error: String processing operation failed"
|
||||
|
||||
#define SPC_ERROR1 "Error: Specifying an alternate JDK/JRE version is no longer supported.\n The use of the flag '-version:' is no longer valid.\n Please download and execute the appropriate version."
|
||||
#define SPC_ERROR2 "Error: Specifying an alternate JDK/JRE is no longer supported.\n The related flags -jre-restrict-search | -jre-no-restrict-search are also no longer valid."
|
||||
|
||||
#define DLL_ERROR1 "Error: dl failure on line %d"
|
||||
#define DLL_ERROR2 "Error: failed %s, because %s"
|
||||
#define DLL_ERROR3 "Error: could not find executable %s"
|
||||
|
|
|
@ -34,20 +34,15 @@
|
|||
|
||||
/*
|
||||
* One job of the launcher is to remove command line options which the
|
||||
* vm does not understand and will not process. These options include
|
||||
* 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.
|
||||
* -server).
|
||||
* 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. The CreateExecutionEnvironment function processes
|
||||
* and removes -d<n> options. On unix, there is a possibility that the running
|
||||
* data model may not match to the desired data model, in this case an exec is
|
||||
* required to start the desired model. If the data models match, then
|
||||
* ParseArguments will remove the -d<n> flags. If the data models do not match
|
||||
* the CreateExecutionEnviroment will remove the -d<n> flags.
|
||||
* removes "-J" prefixes.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -55,11 +50,12 @@
|
|||
|
||||
#include "java.h"
|
||||
#include "jni.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
/*
|
||||
* 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
|
||||
* the program image remain relatively small until after
|
||||
* CreateExecutionEnvironment has finished its possibly recursive
|
||||
* processing. Watch everything, but resist all temptations to use Java
|
||||
* interfaces.
|
||||
*/
|
||||
|
@ -88,10 +84,10 @@ static jboolean _wc_enabled = JNI_FALSE;
|
|||
static jboolean dumpSharedSpaces = JNI_FALSE; /* -Xshare:dump */
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* Values that will be stored into splash screen environment variables.
|
||||
* putenv is performed to set _JAVA_SPLASH_FILE and _JAVA_SPLASH_JAR
|
||||
* with these values. We need them in memory until UnsetEnv in
|
||||
* ShowSplashScreen, so they are made static global instead of auto local.
|
||||
*/
|
||||
static char* splash_file_entry = NULL;
|
||||
static char* splash_jar_entry = NULL;
|
||||
|
@ -110,14 +106,14 @@ static jboolean IsJavaArgs();
|
|||
static void SetJavaLauncherProp();
|
||||
static void SetClassPath(const char *s);
|
||||
static void SetMainModule(const char *s);
|
||||
static void SelectVersion(int argc, char **argv, char **main_class);
|
||||
static jboolean ParseArguments(int *pargc, char ***pargv,
|
||||
int *pmode, char **pwhat,
|
||||
int *pret, const char *jrepath);
|
||||
int *pret);
|
||||
static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
|
||||
InvocationFunctions *ifn);
|
||||
static jstring NewPlatformString(JNIEnv *env, char *s);
|
||||
static jclass LoadMainClass(JNIEnv *env, int mode, char *name);
|
||||
static void SetupSplashScreenEnvVars(const char *splash_file_path, char *jar_path);
|
||||
static jclass GetApplicationClass(JNIEnv *env);
|
||||
|
||||
static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv);
|
||||
|
@ -240,7 +236,6 @@ JLI_Launch(int argc, char ** argv, /* main argc, argv */
|
|||
{
|
||||
int mode = LM_UNKNOWN;
|
||||
char *what = NULL;
|
||||
char *main_class = NULL;
|
||||
int ret;
|
||||
InvocationFunctions ifn;
|
||||
jlong start = 0, end = 0;
|
||||
|
@ -257,6 +252,10 @@ JLI_Launch(int argc, char ** argv, /* main argc, argv */
|
|||
InitLauncher(javaw);
|
||||
DumpState();
|
||||
if (JLI_IsTraceLauncher()) {
|
||||
char *env_in;
|
||||
if ((env_in = getenv(MAIN_CLASS_ENV_ENTRY)) != NULL) {
|
||||
printf("Launched through Multiple JRE (mJRE) support\n");
|
||||
}
|
||||
int i;
|
||||
printf("Java args:\n");
|
||||
for (i = 0; i < jargc ; i++) {
|
||||
|
@ -269,18 +268,6 @@ JLI_Launch(int argc, char ** argv, /* main argc, argv */
|
|||
AddOption("-Dsun.java.launcher.diag=true", NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* SelectVersion() has several responsibilities:
|
||||
*
|
||||
* 1) Disallow specification of another JRE. With 1.9, another
|
||||
* version of the JRE cannot be invoked.
|
||||
* 2) Allow for a JRE version to invoke JDK 1.9 or later. Since
|
||||
* all mJRE directives have been stripped from the request but
|
||||
* the pre 1.9 JRE [ 1.6 thru 1.8 ], it is as if 1.9+ has been
|
||||
* invoked from the command line.
|
||||
*/
|
||||
SelectVersion(argc, argv, &main_class);
|
||||
|
||||
CreateExecutionEnvironment(&argc, &argv,
|
||||
jrepath, sizeof(jrepath),
|
||||
jvmpath, sizeof(jvmpath),
|
||||
|
@ -323,7 +310,7 @@ JLI_Launch(int argc, char ** argv, /* main argc, argv */
|
|||
/* Parse command line options; if the return value of
|
||||
* ParseArguments is false, the program should exit.
|
||||
*/
|
||||
if (!ParseArguments(&argc, &argv, &mode, &what, &ret, jrepath)) {
|
||||
if (!ParseArguments(&argc, &argv, &mode, &what, &ret)) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
@ -1078,167 +1065,6 @@ SetMainModule(const char *s)
|
|||
AddOption(def, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 *operand;
|
||||
int jarflag = 0;
|
||||
int headlessflag = 0;
|
||||
manifest_info info;
|
||||
char *splash_file_name = NULL;
|
||||
char *splash_jar_name = NULL;
|
||||
char *env_in;
|
||||
int res;
|
||||
jboolean has_arg;
|
||||
|
||||
/*
|
||||
* If the version has already been selected, set *main_class
|
||||
* with the value passed through the environment (if any) and
|
||||
* simply return.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This environmental variable can be set by mJRE capable JREs
|
||||
* [ 1.5 thru 1.8 ]. All other aspects of mJRE processing have been
|
||||
* stripped by those JREs. This environmental variable allows 1.9+
|
||||
* JREs to be started by these mJRE capable JREs.
|
||||
* Note that mJRE directives in the jar manifest file would have been
|
||||
* ignored for a JRE started by another JRE...
|
||||
* .. skipped for JRE 1.5 and beyond.
|
||||
* .. not even checked for pre 1.5.
|
||||
*/
|
||||
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. Multiple JRE support existed in JRE versions 1.5 thru 1.8.
|
||||
*
|
||||
* This capability is no longer available with JRE versions 1.9 and later.
|
||||
* These command line options are reported as errors.
|
||||
*/
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
while (argc > 0 && *(arg = *argv) == '-') {
|
||||
has_arg = IsOptionWithArgument(argc, argv);
|
||||
if (JLI_StrCCmp(arg, "-version:") == 0) {
|
||||
JLI_ReportErrorMessage(SPC_ERROR1);
|
||||
} else if (JLI_StrCmp(arg, "-jre-restrict-search") == 0) {
|
||||
JLI_ReportErrorMessage(SPC_ERROR2);
|
||||
} else if (JLI_StrCmp(arg, "-jre-no-restrict-search") == 0) {
|
||||
JLI_ReportErrorMessage(SPC_ERROR2);
|
||||
} else {
|
||||
if (JLI_StrCmp(arg, "-jar") == 0)
|
||||
jarflag = 1;
|
||||
if (IsWhiteSpaceOption(arg)) {
|
||||
if (has_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 (JLI_StrCmp(arg, "-Djava.awt.headless=true") == 0) {
|
||||
headlessflag = 1;
|
||||
} else if (JLI_StrCCmp(arg, "-Djava.awt.headless=") == 0) {
|
||||
headlessflag = 0;
|
||||
} else if (JLI_StrCCmp(arg, "-splash:") == 0) {
|
||||
splash_file_name = arg+8;
|
||||
}
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
if (argc <= 0) { /* No operand? Possibly legit with -[full]version */
|
||||
operand = NULL;
|
||||
} else {
|
||||
argc--;
|
||||
operand = *argv++;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
JLI_ReportErrorMessage(JAR_ERROR2, operand);
|
||||
else
|
||||
JLI_ReportErrorMessage(JAR_ERROR3, operand);
|
||||
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) {
|
||||
splash_file_entry = JLI_MemAlloc(JLI_StrLen(SPLASH_FILE_ENV_ENTRY "=")+JLI_StrLen(splash_file_name)+1);
|
||||
JLI_StrCpy(splash_file_entry, SPLASH_FILE_ENV_ENTRY "=");
|
||||
JLI_StrCat(splash_file_entry, splash_file_name);
|
||||
putenv(splash_file_entry);
|
||||
}
|
||||
if (splash_jar_name && !headlessflag) {
|
||||
splash_jar_entry = JLI_MemAlloc(JLI_StrLen(SPLASH_JAR_ENV_ENTRY "=")+JLI_StrLen(splash_jar_name)+1);
|
||||
JLI_StrCpy(splash_jar_entry, SPLASH_JAR_ENV_ENTRY "=");
|
||||
JLI_StrCat(splash_jar_entry, splash_jar_name);
|
||||
putenv(splash_jar_entry);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "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 (info.jre_version == NULL) {
|
||||
JLI_FreeManifest();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if the current argv is an option, i.e. with a leading `-`
|
||||
* and followed with an argument without a leading `-`.
|
||||
|
@ -1325,12 +1151,14 @@ GetOpt(int *pargc, char ***pargv, char **poption, char **pvalue) {
|
|||
static jboolean
|
||||
ParseArguments(int *pargc, char ***pargv,
|
||||
int *pmode, char **pwhat,
|
||||
int *pret, const char *jrepath)
|
||||
int *pret)
|
||||
{
|
||||
int argc = *pargc;
|
||||
char **argv = *pargv;
|
||||
int mode = LM_UNKNOWN;
|
||||
char *arg = NULL;
|
||||
bool headless = false;
|
||||
char *splash_file_path = NULL; // value of "-splash:" option
|
||||
|
||||
*pret = 0;
|
||||
|
||||
|
@ -1492,7 +1320,7 @@ ParseArguments(int *pargc, char ***pargv,
|
|||
snprintf(tmp, tmpSize, "-X%s", arg + 1); /* skip '-' */
|
||||
AddOption(tmp, NULL);
|
||||
} else if (JLI_StrCCmp(arg, "-splash:") == 0) {
|
||||
; /* Ignore machine independent options already handled */
|
||||
splash_file_path = arg + 8;
|
||||
} else if (JLI_StrCmp(arg, "--disable-@files") == 0) {
|
||||
; /* Ignore --disable-@files option already handled */
|
||||
} else if (ProcessPlatformOption(arg)) {
|
||||
|
@ -1501,6 +1329,14 @@ ParseArguments(int *pargc, char ***pargv,
|
|||
/* java.class.path set on the command line */
|
||||
if (JLI_StrCCmp(arg, "-Djava.class.path=") == 0) {
|
||||
_have_classpath = JNI_TRUE;
|
||||
} else if (JLI_StrCmp(arg, "-Djava.awt.headless=true") == 0) {
|
||||
/*
|
||||
* Checking for headless toolkit option in the same way as AWT does:
|
||||
* "true" means true and any other value means false
|
||||
*/
|
||||
headless = true;
|
||||
} else if (JLI_StrCCmp(arg, "-Djava.awt.headless=") == 0) {
|
||||
headless = false;
|
||||
}
|
||||
AddOption(arg, NULL);
|
||||
}
|
||||
|
@ -1551,9 +1387,82 @@ ParseArguments(int *pargc, char ***pargv,
|
|||
|
||||
*pmode = mode;
|
||||
|
||||
if (!headless) {
|
||||
char *jar_path = NULL;
|
||||
if (mode == LM_JAR) {
|
||||
jar_path = *pwhat;
|
||||
}
|
||||
// Not in headless mode. We now set a couple of env variables that
|
||||
// will be used later by ShowSplashScreen().
|
||||
SetupSplashScreenEnvVars(splash_file_path, jar_path);
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the relevant environment variables that are subsequently used by
|
||||
* the ShowSplashScreen() function. The splash_file_path and jar_path parameters
|
||||
* are used to determine which environment variables to set.
|
||||
* The splash_file_path is the value that was provided to the "-splash:" option
|
||||
* when launching java. It may be null, which implies the "-splash:" option wasn't used.
|
||||
* The jar_path is the value that was provided to the "-jar" option when launching java.
|
||||
* It too may be null, which implies the "-jar" option wasn't used.
|
||||
*/
|
||||
static void
|
||||
SetupSplashScreenEnvVars(const char *splash_file_path, char *jar_path) {
|
||||
// Command line specified "-splash:" takes priority over manifest one.
|
||||
if (splash_file_path) {
|
||||
// We set up the splash file name as a env variable which then gets
|
||||
// used when showing the splash screen in ShowSplashScreen().
|
||||
|
||||
// create the string of the form _JAVA_SPLASH_FILE=<val>
|
||||
splash_file_entry = JLI_MemAlloc(JLI_StrLen(SPLASH_FILE_ENV_ENTRY "=")
|
||||
+ JLI_StrLen(splash_file_path) + 1);
|
||||
JLI_StrCpy(splash_file_entry, SPLASH_FILE_ENV_ENTRY "=");
|
||||
JLI_StrCat(splash_file_entry, splash_file_path);
|
||||
putenv(splash_file_entry);
|
||||
return;
|
||||
}
|
||||
if (!jar_path) {
|
||||
// no jar to look into for "SplashScreen-Image" manifest attribute
|
||||
return;
|
||||
}
|
||||
// parse the jar's manifest to find any "SplashScreen-Image"
|
||||
int res = 0;
|
||||
manifest_info info;
|
||||
if ((res = JLI_ParseManifest(jar_path, &info)) != 0) {
|
||||
JLI_FreeManifest(); // cleanup any manifest structure
|
||||
if (res == -1) {
|
||||
JLI_ReportErrorMessage(JAR_ERROR2, jar_path);
|
||||
} else {
|
||||
JLI_ReportErrorMessage(JAR_ERROR3, jar_path);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
if (!info.splashscreen_image_file_name) {
|
||||
JLI_FreeManifest(); // cleanup the manifest structure
|
||||
// no "SplashScreen-Image" in jar's manifest
|
||||
return;
|
||||
}
|
||||
// The jar's manifest had a "Splashscreen-Image" specified. We set up the jar entry name
|
||||
// and the jar file name as env variables which then get used when showing the splash screen
|
||||
// in ShowSplashScreen().
|
||||
|
||||
// create the string of the form _JAVA_SPLASH_FILE=<val>
|
||||
splash_file_entry = JLI_MemAlloc(JLI_StrLen(SPLASH_FILE_ENV_ENTRY "=")
|
||||
+ JLI_StrLen(info.splashscreen_image_file_name) + 1);
|
||||
JLI_StrCpy(splash_file_entry, SPLASH_FILE_ENV_ENTRY "=");
|
||||
JLI_StrCat(splash_file_entry, info.splashscreen_image_file_name);
|
||||
putenv(splash_file_entry);
|
||||
// create the string of the form _JAVA_SPLASH_JAR=<val>
|
||||
splash_jar_entry = JLI_MemAlloc(JLI_StrLen(SPLASH_JAR_ENV_ENTRY "=") + JLI_StrLen(jar_path) + 1);
|
||||
JLI_StrCpy(splash_jar_entry, SPLASH_JAR_ENV_ENTRY "=");
|
||||
JLI_StrCat(splash_jar_entry, jar_path);
|
||||
putenv(splash_jar_entry);
|
||||
JLI_FreeManifest(); // cleanup the manifest structure
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes the Java Virtual Machine. Also frees options array when
|
||||
* finished.
|
||||
|
@ -2340,7 +2249,7 @@ ShowSplashScreen()
|
|||
* Done with all command line processing and potential re-execs so
|
||||
* clean up the environment.
|
||||
*/
|
||||
(void)UnsetEnv(ENV_ENTRY);
|
||||
(void)UnsetEnv(MAIN_CLASS_ENV_ENTRY);
|
||||
(void)UnsetEnv(SPLASH_FILE_ENV_ENTRY);
|
||||
(void)UnsetEnv(SPLASH_JAR_ENV_ENTRY);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2024, 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
|
||||
|
@ -51,23 +51,19 @@
|
|||
#define CURRENT_DATA_MODEL (CHAR_BIT * sizeof(void*))
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Older versions of java launcher used to support JRE version selection - specifically,
|
||||
* the java launcher in JDK 1.8 can be used to launch a java application using a different
|
||||
* java runtime (older, newer or same version JRE installed at a different location) than
|
||||
* the one the launcher belongs to.
|
||||
* That support was discontinued starting JDK 9. However, the JDK 8 launcher can still
|
||||
* be started with JRE version selection options to launch Java runtimes greater than JDK 8.
|
||||
* In such cases, the JDK 8 launcher when exec()ing the JDK N launcher, will set and propagate
|
||||
* the _JAVA_VERSION_SET environment variable. The value of this environment variable is the
|
||||
* Main-Class name from within the executable jar file (if any).
|
||||
* The java launcher in the current version of the JDK doesn't use this environment variable
|
||||
* in any way other than merely using it in debug logging.
|
||||
*/
|
||||
#define ENV_ENTRY "_JAVA_VERSION_SET"
|
||||
#define MAIN_CLASS_ENV_ENTRY "_JAVA_VERSION_SET"
|
||||
|
||||
#define SPLASH_FILE_ENV_ENTRY "_JAVA_SPLASH_FILE"
|
||||
#define SPLASH_JAR_ENV_ENTRY "_JAVA_SPLASH_JAR"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2024, 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
|
||||
|
@ -167,10 +167,6 @@ typedef struct zentry { /* Zip file entry */
|
|||
* Java launcher).
|
||||
*/
|
||||
typedef struct manifest_info { /* Interesting fields from the Manifest */
|
||||
char *manifest_version; /* Manifest-Version string */
|
||||
char *main_class; /* Main-Class entry */
|
||||
char *jre_version; /* Appropriate J2SE release spec */
|
||||
char jre_restrict_search; /* Restricted JRE search */
|
||||
char *splashscreen_image_file_name; /* splashscreen image file */
|
||||
} manifest_info;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2024, 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
|
||||
|
@ -594,10 +594,6 @@ JLI_ParseManifest(char *jarfile, manifest_info *info)
|
|||
)) == -1) {
|
||||
return (-1);
|
||||
}
|
||||
info->manifest_version = NULL;
|
||||
info->main_class = NULL;
|
||||
info->jre_version = NULL;
|
||||
info->jre_restrict_search = 0;
|
||||
info->splashscreen_image_file_name = NULL;
|
||||
if ((rc = find_file(fd, &entry, manifest_name)) != 0) {
|
||||
close(fd);
|
||||
|
@ -610,17 +606,7 @@ JLI_ParseManifest(char *jarfile, manifest_info *info)
|
|||
}
|
||||
lp = manifest;
|
||||
while ((rc = parse_nv_pair(&lp, &name, &value)) > 0) {
|
||||
if (JLI_StrCaseCmp(name, "Manifest-Version") == 0) {
|
||||
info->manifest_version = value;
|
||||
} else if (JLI_StrCaseCmp(name, "Main-Class") == 0) {
|
||||
info->main_class = value;
|
||||
} else if (JLI_StrCaseCmp(name, "JRE-Version") == 0) {
|
||||
/*
|
||||
* Manifest specification overridden by command line option
|
||||
* so we will silently override there with no specification.
|
||||
*/
|
||||
info->jre_version = 0;
|
||||
} else if (JLI_StrCaseCmp(name, "Splashscreen-Image") == 0) {
|
||||
if (JLI_StrCaseCmp(name, "Splashscreen-Image") == 0) {
|
||||
info->splashscreen_image_file_name = value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,102 +52,86 @@
|
|||
#endif
|
||||
|
||||
/*
|
||||
* Flowchart of launcher execs and options processing on unix
|
||||
* Following is the high level flow of the launcher
|
||||
* code residing in the common java.c and this
|
||||
* unix specific java_md file:
|
||||
*
|
||||
* The selection of the proper vm shared library to open depends on
|
||||
* several classes of command line options, including vm "flavor"
|
||||
* options (-client, -server).
|
||||
* The vm selection options are not passed to the running
|
||||
* virtual machine; they must be screened out by the launcher.
|
||||
* - JLI_Launch function, which is the entry point
|
||||
* to the launcher, calls CreateExecutionEnvironment.
|
||||
*
|
||||
* 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.
|
||||
* - CreateExecutionEnvironment does the following
|
||||
* (not necessarily in this order):
|
||||
* - determines the relevant JVM type that
|
||||
* needs to be ultimately created
|
||||
* - determines the path and asserts the presence
|
||||
* of libjava and relevant libjvm library
|
||||
* - removes any JVM selection options from the
|
||||
* arguments that were passed to the launcher
|
||||
*
|
||||
* Previously the launcher modified the LD_LIBRARY_PATH appropriately for the
|
||||
* desired data model path, regardless if data models matched or not. The
|
||||
* launcher subsequently exec'ed the desired executable, in order to make the
|
||||
* LD_LIBRARY_PATH path available, for the runtime linker.
|
||||
* - CreateExecutionEnvironment then determines (by calling
|
||||
* RequiresSetenv function) if LD_LIBRARY_PATH environment
|
||||
* variable needs to be set/updated.
|
||||
* - If LD_LIBRARY_PATH needs to be set/updated,
|
||||
* then CreateExecutionEnvironment exec()s
|
||||
* the current process with the appropriate value
|
||||
* for LD_LIBRARY_PATH.
|
||||
* - Else if LD_LIBRARY_PATH need not be set or
|
||||
* updated, then CreateExecutionEnvironment
|
||||
* returns back.
|
||||
*
|
||||
* Now, in most cases,the launcher will dlopen the target libjvm.so. All
|
||||
* required libraries are loaded by the runtime linker, using the
|
||||
* $RPATH/$ORIGIN baked into the shared libraries at compile time. Therefore,
|
||||
* in most cases, the launcher will only exec, if the data models are
|
||||
* mismatched, and will not set any environment variables, regardless of the
|
||||
* data models.
|
||||
* - If CreateExecutionEnvironment exec()ed the process
|
||||
* in the previous step, then the code control for the
|
||||
* process will again start from the process' entry
|
||||
* point and JLI_Launch is thus re-invoked and the
|
||||
* same above sequence of code flow repeats again.
|
||||
* During this "recursive" call into CreateExecutionEnvironment,
|
||||
* the implementation of the check for LD_LIBRARY_PATH
|
||||
* will realize that no further exec() is required and
|
||||
* the control will return back from CreateExecutionEnvironment.
|
||||
*
|
||||
* However, if the environment contains a LD_LIBRARY_PATH, this will cause the
|
||||
* launcher to inspect the LD_LIBRARY_PATH. The launcher will check
|
||||
* a. if the LD_LIBRARY_PATH's first component is the path to the desired
|
||||
* libjvm.so
|
||||
* b. if any other libjvm.so is found in any of the paths.
|
||||
* If case b is true, then the launcher will set the LD_LIBRARY_PATH to the
|
||||
* desired JRE and reexec, in order to propagate the environment.
|
||||
* - The control returns back from CreateExecutionEnvironment
|
||||
* to JLI_Launch.
|
||||
*
|
||||
* Main
|
||||
* (incoming argv)
|
||||
* |
|
||||
* \|/
|
||||
* CreateExecutionEnvironment
|
||||
* (determines desired data model)
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* Have Desired Model ? --> NO --> Exit(with error)
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* YES
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* CheckJvmType
|
||||
* (removes -client, -server, etc.)
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* TranslateDashJArgs...
|
||||
* (Prepare to pass args to vm)
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* ParseArguments
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* RequiresSetenv
|
||||
* Is LD_LIBRARY_PATH
|
||||
* and friends set ? --> NO --> Continue
|
||||
* YES
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* Path is desired JRE ? YES --> Continue
|
||||
* NO
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* Paths have well known
|
||||
* jvm paths ? --> NO --> Error/Exit
|
||||
* YES
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* Does libjvm.so exist
|
||||
* in any of them ? --> NO --> Continue
|
||||
* YES
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* Set the LD_LIBRARY_PATH
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* Re-exec
|
||||
* |
|
||||
* |
|
||||
* \|/
|
||||
* Main
|
||||
* - JLI_Launch then invokes LoadJavaVM which dlopen()s
|
||||
* the JVM library and asserts the presence of
|
||||
* JNI Invocation Functions "JNI_CreateJavaVM",
|
||||
* "JNI_GetDefaultJavaVMInitArgs" and
|
||||
* "JNI_GetCreatedJavaVMs" in that library. It then
|
||||
* sets internal function pointers in the launcher to
|
||||
* point to those functions.
|
||||
*
|
||||
* - JLI_Launch then translates any -J options by
|
||||
* invoking TranslateApplicationArgs.
|
||||
*
|
||||
* - JLI_Launch then invokes ParseArguments to
|
||||
* parse/process the launcher arguments.
|
||||
*
|
||||
* - JLI_Launch then ultimately calls JVMInit.
|
||||
*
|
||||
* - JVMInit invokes ShowSplashScreen which displays
|
||||
* a splash screen for the application, if applicable.
|
||||
*
|
||||
* - JVMInit then creates a new thread (T2), in the
|
||||
* current process, and invokes JavaMain function
|
||||
* in that new thread. The current thread (T1) then
|
||||
* waits for the newly launched thread (T2) to complete.
|
||||
*
|
||||
* - JavaMain function, in thread T2, before launching
|
||||
* the application, invokes PostJVMInit.
|
||||
*
|
||||
* - PostJVMInit is a no-op and returns back.
|
||||
*
|
||||
* - Control then returns back from PostJVMInit into JavaMain,
|
||||
* which then loads the application's main class and invokes
|
||||
* the relevant main() Java method.
|
||||
*
|
||||
* - JavaMain, in thread T2, then returns back an integer
|
||||
* result and thread T2 execution ends here.
|
||||
*
|
||||
* - The thread T1 in JVMInit, which is waiting on T2 to
|
||||
* complete, receives the integer result and then propagates
|
||||
* it as a return value all the way out of the
|
||||
* JLI_Launch function.
|
||||
*/
|
||||
|
||||
/* Store the name of the executable once computed */
|
||||
|
@ -221,7 +205,7 @@ ContainsLibJVM(const char *env) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Test whether the environment variable needs to be set, see flowchart.
|
||||
* Test whether the LD_LIBRARY_PATH environment variable needs to be set.
|
||||
*/
|
||||
static jboolean
|
||||
RequiresSetenv(const char *jvmpath) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue