mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +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"
|
#define LD_LIBRARY_PATH "DYLD_FALLBACK_LIBRARY_PATH"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If a processor / os combination has the ability to run binaries of
|
* Following is the high level flow of the launcher
|
||||||
* two data models and cohabitation of jre/jdk bits with both data
|
* code residing in the common java.c and this
|
||||||
* models is supported, then DUAL_MODE is defined. MacOSX is a hybrid
|
* macosx specific java_md_macosx file:
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
* Notes:
|
* - JLI_Launch function, which is the entry point
|
||||||
* 1. VM. DUAL_MODE is disabled, and not supported, however, it is left here in
|
* to the launcher, calls CreateExecutionEnvironment.
|
||||||
* 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
|
|
||||||
*
|
*
|
||||||
* The selection of the proper vm shared library to open depends on
|
* - CreateExecutionEnvironment does the following
|
||||||
* several classes of command line options, including vm "flavor"
|
* (not necessarily in this order):
|
||||||
* options (-client, -server) and the data model options, -d32 and
|
* - determines the relevant JVM type that needs
|
||||||
* -d64, as well as a version specification which may have come from
|
* to be ultimately created
|
||||||
* the command line or from the manifest of an executable jar file.
|
* - determines the path and asserts the presence
|
||||||
* The vm selection options are not passed to the running
|
* of libjava and relevant libjvm library
|
||||||
* virtual machine; they must be screened out by the launcher.
|
* - removes any JVM selection options from the
|
||||||
|
* arguments that were passed to the launcher
|
||||||
*
|
*
|
||||||
* The version specification (if any) is processed first by the
|
* - CreateExecutionEnvironment then creates a new
|
||||||
* platform independent routine SelectVersion. This may result in
|
* thread, within the same process, to launch the
|
||||||
* the exec of the specified launcher version.
|
* 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
|
* - The newly created thread (in which the application's
|
||||||
* required libraries are loaded by the runtime linker, using the known paths
|
* main() method will ultimately run) starts right from
|
||||||
* baked into the shared libraries at compile time. Therefore,
|
* the beginning of the current process' main function,
|
||||||
* in most cases, the launcher will only exec, if the data models are
|
* which effectively means that JLI_Launch is re-invoked
|
||||||
* mismatched, and will not set any environment variables, regardless of the
|
* on this new thread and the same above sequence of code
|
||||||
* data models.
|
* 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
|
* - JLI_Launch then translates any -J options by invoking
|
||||||
* (incoming argv)
|
* TranslateApplicationArgs.
|
||||||
* |
|
*
|
||||||
* \|/
|
* - JLI_Launch then invokes ParseArguments to parse/process
|
||||||
* CreateExecutionEnvironment
|
* the launcher arguments.
|
||||||
* (determines desired data model)
|
*
|
||||||
* |
|
* - JLI_Launch then ultimately calls JVMInit.
|
||||||
* |
|
*
|
||||||
* \|/
|
* - JVMInit then invokes JavaMain.
|
||||||
* Have Desired Model ? --> NO --> Is Dual-Mode ? --> NO --> Exit(with error)
|
*
|
||||||
* | |
|
* - JavaMain, before launching the application, invokes
|
||||||
* | |
|
* PostJVMInit.
|
||||||
* | \|/
|
*
|
||||||
* | YES
|
* - PostJVMInit invokes ShowSplashScreen which displays
|
||||||
* | |
|
* a splash screen for the application, if applicable.
|
||||||
* | |
|
*
|
||||||
* | \|/
|
* - Control then returns back from PostJVMInit into
|
||||||
* | CheckJvmType
|
* JavaMain, which then loads the application's main
|
||||||
* | (removes -client, -server etc.)
|
* 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
|
||||||
* YES Find the desired executable/library
|
* out of the JLI_Launch function.
|
||||||
* | |
|
|
||||||
* | |
|
|
||||||
* \|/ \|/
|
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Store the name of the executable once computed */
|
/* Store the name of the executable once computed */
|
||||||
|
|
|
@ -103,9 +103,6 @@
|
||||||
#define JRE_ERROR12 "Error: Exec of %s failed"
|
#define JRE_ERROR12 "Error: Exec of %s failed"
|
||||||
#define JRE_ERROR13 "Error: String processing operation 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_ERROR1 "Error: dl failure on line %d"
|
||||||
#define DLL_ERROR2 "Error: failed %s, because %s"
|
#define DLL_ERROR2 "Error: failed %s, because %s"
|
||||||
#define DLL_ERROR3 "Error: could not find executable %s"
|
#define DLL_ERROR3 "Error: could not find executable %s"
|
||||||
|
|
|
@ -36,18 +36,13 @@
|
||||||
* One job of the launcher is to remove command line options which the
|
* 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
|
* 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"
|
* Additionally, for tools which invoke an underlying vm "-J-foo"
|
||||||
* options are turned into "-foo" options to the vm. This option
|
* options are turned into "-foo" options to the vm. This option
|
||||||
* filtering is handled in a number of places in the launcher, some of
|
* filtering is handled in a number of places in the launcher, some of
|
||||||
* it in machine-dependent code. In this file, the function
|
* it in machine-dependent code. In this file, the function
|
||||||
* CheckJvmType removes vm style options and TranslateApplicationArgs
|
* CheckJvmType removes vm style options and TranslateApplicationArgs
|
||||||
* removes "-J" prefixes. The CreateExecutionEnvironment function processes
|
* removes "-J" prefixes.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,11 +50,12 @@
|
||||||
|
|
||||||
#include "java.h"
|
#include "java.h"
|
||||||
#include "jni.h"
|
#include "jni.h"
|
||||||
|
#include "stdbool.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A NOTE TO DEVELOPERS: For performance reasons it is important that
|
* A NOTE TO DEVELOPERS: For performance reasons it is important that
|
||||||
* the program image remain relatively small until after SelectVersion
|
* the program image remain relatively small until after
|
||||||
* CreateExecutionEnvironment have finished their possibly recursive
|
* CreateExecutionEnvironment has finished its possibly recursive
|
||||||
* processing. Watch everything, but resist all temptations to use Java
|
* processing. Watch everything, but resist all temptations to use Java
|
||||||
* interfaces.
|
* interfaces.
|
||||||
*/
|
*/
|
||||||
|
@ -88,10 +84,10 @@ static jboolean _wc_enabled = JNI_FALSE;
|
||||||
static jboolean dumpSharedSpaces = JNI_FALSE; /* -Xshare:dump */
|
static jboolean dumpSharedSpaces = JNI_FALSE; /* -Xshare:dump */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Entries for splash screen environment variables.
|
* Values that will be stored into splash screen environment variables.
|
||||||
* putenv is performed in SelectVersion. We need
|
* putenv is performed to set _JAVA_SPLASH_FILE and _JAVA_SPLASH_JAR
|
||||||
* them in memory until UnsetEnv, so they are made static
|
* with these values. We need them in memory until UnsetEnv in
|
||||||
* global instead of auto local.
|
* ShowSplashScreen, so they are made static global instead of auto local.
|
||||||
*/
|
*/
|
||||||
static char* splash_file_entry = NULL;
|
static char* splash_file_entry = NULL;
|
||||||
static char* splash_jar_entry = NULL;
|
static char* splash_jar_entry = NULL;
|
||||||
|
@ -110,14 +106,14 @@ static jboolean IsJavaArgs();
|
||||||
static void SetJavaLauncherProp();
|
static void SetJavaLauncherProp();
|
||||||
static void SetClassPath(const char *s);
|
static void SetClassPath(const char *s);
|
||||||
static void SetMainModule(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,
|
static jboolean ParseArguments(int *pargc, char ***pargv,
|
||||||
int *pmode, char **pwhat,
|
int *pmode, char **pwhat,
|
||||||
int *pret, const char *jrepath);
|
int *pret);
|
||||||
static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
|
static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
|
||||||
InvocationFunctions *ifn);
|
InvocationFunctions *ifn);
|
||||||
static jstring NewPlatformString(JNIEnv *env, char *s);
|
static jstring NewPlatformString(JNIEnv *env, char *s);
|
||||||
static jclass LoadMainClass(JNIEnv *env, int mode, char *name);
|
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 jclass GetApplicationClass(JNIEnv *env);
|
||||||
|
|
||||||
static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv);
|
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;
|
int mode = LM_UNKNOWN;
|
||||||
char *what = NULL;
|
char *what = NULL;
|
||||||
char *main_class = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
InvocationFunctions ifn;
|
InvocationFunctions ifn;
|
||||||
jlong start = 0, end = 0;
|
jlong start = 0, end = 0;
|
||||||
|
@ -257,6 +252,10 @@ JLI_Launch(int argc, char ** argv, /* main argc, argv */
|
||||||
InitLauncher(javaw);
|
InitLauncher(javaw);
|
||||||
DumpState();
|
DumpState();
|
||||||
if (JLI_IsTraceLauncher()) {
|
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;
|
int i;
|
||||||
printf("Java args:\n");
|
printf("Java args:\n");
|
||||||
for (i = 0; i < jargc ; i++) {
|
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);
|
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,
|
CreateExecutionEnvironment(&argc, &argv,
|
||||||
jrepath, sizeof(jrepath),
|
jrepath, sizeof(jrepath),
|
||||||
jvmpath, sizeof(jvmpath),
|
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
|
/* Parse command line options; if the return value of
|
||||||
* ParseArguments is false, the program should exit.
|
* ParseArguments is false, the program should exit.
|
||||||
*/
|
*/
|
||||||
if (!ParseArguments(&argc, &argv, &mode, &what, &ret, jrepath)) {
|
if (!ParseArguments(&argc, &argv, &mode, &what, &ret)) {
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1078,167 +1065,6 @@ SetMainModule(const char *s)
|
||||||
AddOption(def, NULL);
|
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 `-`
|
* Test if the current argv is an option, i.e. with a leading `-`
|
||||||
* and followed with an argument without 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
|
static jboolean
|
||||||
ParseArguments(int *pargc, char ***pargv,
|
ParseArguments(int *pargc, char ***pargv,
|
||||||
int *pmode, char **pwhat,
|
int *pmode, char **pwhat,
|
||||||
int *pret, const char *jrepath)
|
int *pret)
|
||||||
{
|
{
|
||||||
int argc = *pargc;
|
int argc = *pargc;
|
||||||
char **argv = *pargv;
|
char **argv = *pargv;
|
||||||
int mode = LM_UNKNOWN;
|
int mode = LM_UNKNOWN;
|
||||||
char *arg = NULL;
|
char *arg = NULL;
|
||||||
|
bool headless = false;
|
||||||
|
char *splash_file_path = NULL; // value of "-splash:" option
|
||||||
|
|
||||||
*pret = 0;
|
*pret = 0;
|
||||||
|
|
||||||
|
@ -1492,7 +1320,7 @@ ParseArguments(int *pargc, char ***pargv,
|
||||||
snprintf(tmp, tmpSize, "-X%s", arg + 1); /* skip '-' */
|
snprintf(tmp, tmpSize, "-X%s", arg + 1); /* skip '-' */
|
||||||
AddOption(tmp, NULL);
|
AddOption(tmp, NULL);
|
||||||
} else if (JLI_StrCCmp(arg, "-splash:") == 0) {
|
} 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) {
|
} else if (JLI_StrCmp(arg, "--disable-@files") == 0) {
|
||||||
; /* Ignore --disable-@files option already handled */
|
; /* Ignore --disable-@files option already handled */
|
||||||
} else if (ProcessPlatformOption(arg)) {
|
} else if (ProcessPlatformOption(arg)) {
|
||||||
|
@ -1501,6 +1329,14 @@ ParseArguments(int *pargc, char ***pargv,
|
||||||
/* java.class.path set on the command line */
|
/* java.class.path set on the command line */
|
||||||
if (JLI_StrCCmp(arg, "-Djava.class.path=") == 0) {
|
if (JLI_StrCCmp(arg, "-Djava.class.path=") == 0) {
|
||||||
_have_classpath = JNI_TRUE;
|
_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);
|
AddOption(arg, NULL);
|
||||||
}
|
}
|
||||||
|
@ -1551,9 +1387,82 @@ ParseArguments(int *pargc, char ***pargv,
|
||||||
|
|
||||||
*pmode = mode;
|
*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;
|
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
|
* Initializes the Java Virtual Machine. Also frees options array when
|
||||||
* finished.
|
* finished.
|
||||||
|
@ -2340,7 +2249,7 @@ ShowSplashScreen()
|
||||||
* Done with all command line processing and potential re-execs so
|
* Done with all command line processing and potential re-execs so
|
||||||
* clean up the environment.
|
* clean up the environment.
|
||||||
*/
|
*/
|
||||||
(void)UnsetEnv(ENV_ENTRY);
|
(void)UnsetEnv(MAIN_CLASS_ENV_ENTRY);
|
||||||
(void)UnsetEnv(SPLASH_FILE_ENV_ENTRY);
|
(void)UnsetEnv(SPLASH_FILE_ENV_ENTRY);
|
||||||
(void)UnsetEnv(SPLASH_JAR_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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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*))
|
#define CURRENT_DATA_MODEL (CHAR_BIT * sizeof(void*))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following environment variable is used to influence the behavior
|
* Older versions of java launcher used to support JRE version selection - specifically,
|
||||||
* of the jre exec'd through the SelectVersion routine. The command line
|
* the java launcher in JDK 1.8 can be used to launch a java application using a different
|
||||||
* options which specify the version are not passed to the exec'd version,
|
* java runtime (older, newer or same version JRE installed at a different location) than
|
||||||
* because that jre may be an older version which wouldn't recognize them.
|
* the one the launcher belongs to.
|
||||||
* This environment variable is known to this (and later) version and serves
|
* That support was discontinued starting JDK 9. However, the JDK 8 launcher can still
|
||||||
* to suppress the version selection code. This is not only for efficiency,
|
* be started with JRE version selection options to launch Java runtimes greater than JDK 8.
|
||||||
* but also for correctness, since any command line options have been
|
* In such cases, the JDK 8 launcher when exec()ing the JDK N launcher, will set and propagate
|
||||||
* removed which would cause any value found in the manifest to be used.
|
* the _JAVA_VERSION_SET environment variable. The value of this environment variable is the
|
||||||
* This would be incorrect because the command line options are defined
|
* Main-Class name from within the executable jar file (if any).
|
||||||
* to take precedence.
|
* 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.
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
#define ENV_ENTRY "_JAVA_VERSION_SET"
|
#define MAIN_CLASS_ENV_ENTRY "_JAVA_VERSION_SET"
|
||||||
|
|
||||||
#define SPLASH_FILE_ENV_ENTRY "_JAVA_SPLASH_FILE"
|
#define SPLASH_FILE_ENV_ENTRY "_JAVA_SPLASH_FILE"
|
||||||
#define SPLASH_JAR_ENV_ENTRY "_JAVA_SPLASH_JAR"
|
#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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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).
|
* Java launcher).
|
||||||
*/
|
*/
|
||||||
typedef struct manifest_info { /* Interesting fields from the Manifest */
|
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 */
|
char *splashscreen_image_file_name; /* splashscreen image file */
|
||||||
} manifest_info;
|
} 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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) {
|
)) == -1) {
|
||||||
return (-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;
|
info->splashscreen_image_file_name = NULL;
|
||||||
if ((rc = find_file(fd, &entry, manifest_name)) != 0) {
|
if ((rc = find_file(fd, &entry, manifest_name)) != 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -610,17 +606,7 @@ JLI_ParseManifest(char *jarfile, manifest_info *info)
|
||||||
}
|
}
|
||||||
lp = manifest;
|
lp = manifest;
|
||||||
while ((rc = parse_nv_pair(&lp, &name, &value)) > 0) {
|
while ((rc = parse_nv_pair(&lp, &name, &value)) > 0) {
|
||||||
if (JLI_StrCaseCmp(name, "Manifest-Version") == 0) {
|
if (JLI_StrCaseCmp(name, "Splashscreen-Image") == 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) {
|
|
||||||
info->splashscreen_image_file_name = value;
|
info->splashscreen_image_file_name = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,102 +52,86 @@
|
||||||
#endif
|
#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
|
* - JLI_Launch function, which is the entry point
|
||||||
* several classes of command line options, including vm "flavor"
|
* to the launcher, calls CreateExecutionEnvironment.
|
||||||
* options (-client, -server).
|
|
||||||
* 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
|
* - CreateExecutionEnvironment does the following
|
||||||
* platform independent routine SelectVersion. This may result in
|
* (not necessarily in this order):
|
||||||
* the exec of the specified launcher version.
|
* - 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
|
* - CreateExecutionEnvironment then determines (by calling
|
||||||
* desired data model path, regardless if data models matched or not. The
|
* RequiresSetenv function) if LD_LIBRARY_PATH environment
|
||||||
* launcher subsequently exec'ed the desired executable, in order to make the
|
* variable needs to be set/updated.
|
||||||
* LD_LIBRARY_PATH path available, for the runtime linker.
|
* - 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
|
* - If CreateExecutionEnvironment exec()ed the process
|
||||||
* required libraries are loaded by the runtime linker, using the
|
* in the previous step, then the code control for the
|
||||||
* $RPATH/$ORIGIN baked into the shared libraries at compile time. Therefore,
|
* process will again start from the process' entry
|
||||||
* in most cases, the launcher will only exec, if the data models are
|
* point and JLI_Launch is thus re-invoked and the
|
||||||
* mismatched, and will not set any environment variables, regardless of the
|
* same above sequence of code flow repeats again.
|
||||||
* data models.
|
* 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
|
* - The control returns back from CreateExecutionEnvironment
|
||||||
* launcher to inspect the LD_LIBRARY_PATH. The launcher will check
|
* to JLI_Launch.
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
* Main
|
* - JLI_Launch then invokes LoadJavaVM which dlopen()s
|
||||||
* (incoming argv)
|
* the JVM library and asserts the presence of
|
||||||
* |
|
* JNI Invocation Functions "JNI_CreateJavaVM",
|
||||||
* \|/
|
* "JNI_GetDefaultJavaVMInitArgs" and
|
||||||
* CreateExecutionEnvironment
|
* "JNI_GetCreatedJavaVMs" in that library. It then
|
||||||
* (determines desired data model)
|
* sets internal function pointers in the launcher to
|
||||||
* |
|
* point to those functions.
|
||||||
* |
|
*
|
||||||
* \|/
|
* - JLI_Launch then translates any -J options by
|
||||||
* Have Desired Model ? --> NO --> Exit(with error)
|
* invoking TranslateApplicationArgs.
|
||||||
* |
|
*
|
||||||
* |
|
* - JLI_Launch then invokes ParseArguments to
|
||||||
* \|/
|
* parse/process the launcher arguments.
|
||||||
* YES
|
*
|
||||||
* |
|
* - JLI_Launch then ultimately calls JVMInit.
|
||||||
* |
|
*
|
||||||
* \|/
|
* - JVMInit invokes ShowSplashScreen which displays
|
||||||
* CheckJvmType
|
* a splash screen for the application, if applicable.
|
||||||
* (removes -client, -server, etc.)
|
*
|
||||||
* |
|
* - JVMInit then creates a new thread (T2), in the
|
||||||
* |
|
* current process, and invokes JavaMain function
|
||||||
* \|/
|
* in that new thread. The current thread (T1) then
|
||||||
* TranslateDashJArgs...
|
* waits for the newly launched thread (T2) to complete.
|
||||||
* (Prepare to pass args to vm)
|
*
|
||||||
* |
|
* - JavaMain function, in thread T2, before launching
|
||||||
* |
|
* the application, invokes PostJVMInit.
|
||||||
* \|/
|
*
|
||||||
* ParseArguments
|
* - 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
|
||||||
* RequiresSetenv
|
* the relevant main() Java method.
|
||||||
* Is LD_LIBRARY_PATH
|
*
|
||||||
* and friends set ? --> NO --> Continue
|
* - JavaMain, in thread T2, then returns back an integer
|
||||||
* YES
|
* 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
|
||||||
* Path is desired JRE ? YES --> Continue
|
* it as a return value all the way out of the
|
||||||
* NO
|
* JLI_Launch function.
|
||||||
* |
|
|
||||||
* |
|
|
||||||
* \|/
|
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Store the name of the executable once computed */
|
/* 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
|
static jboolean
|
||||||
RequiresSetenv(const char *jvmpath) {
|
RequiresSetenv(const char *jvmpath) {
|
||||||
|
|
|
@ -1,214 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2014, 2015, 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
* @bug 8067437
|
|
||||||
* @summary Verify Multiple JRE version support has been removed.
|
|
||||||
* @modules jdk.compiler
|
|
||||||
* jdk.zipfs
|
|
||||||
* @build TestHelper
|
|
||||||
* @run main MultipleJRERemoved
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.jar.Attributes;
|
|
||||||
import java.util.jar.JarOutputStream;
|
|
||||||
import java.util.jar.Manifest;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
|
|
||||||
public class MultipleJRERemoved extends TestHelper {
|
|
||||||
|
|
||||||
public static final String VERSION_JAR = "version.jar";
|
|
||||||
public static final String PRINT_VERSION_CLASS = "PrintVersion";
|
|
||||||
private final File javaFile = new File(PRINT_VERSION_CLASS + ".java");
|
|
||||||
private final File clsFile = new File(PRINT_VERSION_CLASS + ".class");
|
|
||||||
|
|
||||||
private MultipleJRERemoved() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param args the command line arguments
|
|
||||||
* @throws java.io.FileNotFoundException
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
MultipleJRERemoved a = new MultipleJRERemoved();
|
|
||||||
a.run(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check all combinations of flags: "-version:", "-jre-restrict-search", "-jre-no-restrict-search". Test expects to see errors.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void allFlagCombinations() throws IOException {
|
|
||||||
final Pattern newLine = Pattern.compile("\n");
|
|
||||||
createJar(Collections.emptyMap());
|
|
||||||
|
|
||||||
for (Flag flag1 : Flag.values()) {
|
|
||||||
for (Flag flag2 : Flag.values()) {
|
|
||||||
for (Flag flag3 : Flag.values()) {
|
|
||||||
List<Flag> flags = Stream.of(flag1, flag2, flag3)
|
|
||||||
.filter(f -> !Flag.EMPTY.equals(f))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
if (flags.size() == 0) continue;
|
|
||||||
|
|
||||||
List<String> flagValues = flags.stream()
|
|
||||||
.map(Flag::value)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
List<String> errorMessages = flags.stream()
|
|
||||||
.map(Flag::errorMessage)
|
|
||||||
.flatMap(newLine::splitAsStream)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
List<String> jarCmd = new ArrayList<>();
|
|
||||||
jarCmd.add(javaCmd);
|
|
||||||
jarCmd.addAll(flagValues);
|
|
||||||
jarCmd.add("-jar");
|
|
||||||
jarCmd.add("version.jar");
|
|
||||||
|
|
||||||
check(jarCmd, errorMessages);
|
|
||||||
|
|
||||||
List<String> cmd = new ArrayList<>();
|
|
||||||
cmd.add(javaCmd);
|
|
||||||
cmd.addAll(flagValues);
|
|
||||||
cmd.add(PRINT_VERSION_CLASS);
|
|
||||||
|
|
||||||
check(cmd, errorMessages);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void check(List<String> cmd, List<String> errorMessages) {
|
|
||||||
TestResult tr = doExec(cmd.toArray(new String[cmd.size()]));
|
|
||||||
tr.checkNegative();
|
|
||||||
tr.isNotZeroOutput();
|
|
||||||
errorMessages.forEach(tr::contains);
|
|
||||||
|
|
||||||
if (!tr.testStatus) {
|
|
||||||
System.out.println(tr);
|
|
||||||
throw new RuntimeException("test case: failed\n" + cmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies that java -help output doesn't contain information about "mJRE" flags.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void javaHelp() {
|
|
||||||
TestResult tr = doExec(javaCmd, "-help");
|
|
||||||
tr.checkPositive();
|
|
||||||
tr.isNotZeroOutput();
|
|
||||||
tr.notContains("-version:<value>");
|
|
||||||
tr.notContains("-jre-restrict-search");
|
|
||||||
tr.notContains("-jre-no-restrict-search");
|
|
||||||
tr.notContains("-no-jre-restrict-search"); //it's not a typo in flag name.
|
|
||||||
if (!tr.testStatus) {
|
|
||||||
System.out.println(tr);
|
|
||||||
throw new RuntimeException("Failed. java -help output contains obsolete flags.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies that java -jar version.jar output ignores "mJRE" manifest directives.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void manifestDirectives() throws IOException {
|
|
||||||
Map<String, String> manifest = new TreeMap<>();
|
|
||||||
manifest.put("JRE-Version", "1.8");
|
|
||||||
manifest.put("JRE-Restrict-Search", "1.8");
|
|
||||||
createJar(manifest);
|
|
||||||
|
|
||||||
TestResult tr = doExec(javaCmd, "-jar", VERSION_JAR);
|
|
||||||
tr.checkPositive();
|
|
||||||
tr.contains(System.getProperty("java.version"));
|
|
||||||
if (!tr.testStatus) {
|
|
||||||
System.out.println(tr);
|
|
||||||
throw new RuntimeException("Failed.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void emitFile() throws IOException {
|
|
||||||
List<String> scr = new ArrayList<>();
|
|
||||||
scr.add("public class PrintVersion {");
|
|
||||||
scr.add(" public static void main(String... args) {");
|
|
||||||
scr.add(" System.out.println(System.getProperty(\"java.version\"));");
|
|
||||||
scr.add(" }");
|
|
||||||
scr.add("}");
|
|
||||||
createFile(javaFile, scr);
|
|
||||||
compile(javaFile.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createJar(Map<String, String> manifestAttributes) throws IOException {
|
|
||||||
emitFile();
|
|
||||||
|
|
||||||
Manifest manifest = new Manifest();
|
|
||||||
final Attributes mainAttributes = manifest.getMainAttributes();
|
|
||||||
mainAttributes.putValue("Manifest-Version", "1.0");
|
|
||||||
mainAttributes.putValue("Main-Class", PRINT_VERSION_CLASS);
|
|
||||||
manifestAttributes.forEach(mainAttributes::putValue);
|
|
||||||
|
|
||||||
try (JarOutputStream jar = new JarOutputStream(new FileOutputStream(VERSION_JAR), manifest)) {
|
|
||||||
jar.putNextEntry(new ZipEntry(PRINT_VERSION_CLASS + ".class"));
|
|
||||||
jar.write(Files.readAllBytes(clsFile.toPath()));
|
|
||||||
jar.closeEntry();
|
|
||||||
} finally {
|
|
||||||
javaFile.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum Flag {
|
|
||||||
EMPTY("", ""),
|
|
||||||
VERSION("-version:1.9", "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."),
|
|
||||||
JRE_RESTRICT_SEARCH("-jre-restrict-search", "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."),
|
|
||||||
JRE_NO_RESTRICT_SEARCH("-jre-no-restrict-search", "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.");
|
|
||||||
private final String flag;
|
|
||||||
private final String errorMessage;
|
|
||||||
|
|
||||||
Flag(String flag, String errorMessage) {
|
|
||||||
this.flag = flag;
|
|
||||||
this.errorMessage = errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
String value() {
|
|
||||||
return flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
String errorMessage() {
|
|
||||||
return errorMessage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue