199 _fVersion = fullversion;
200 _dVersion = dotversion;
201 _launcher_name = lname;
202 _program_name = pname;
203 _is_java_args = javaargs;
204 _wc_enabled = cpwildcard;
205 _ergo_policy = ergo;
206
207 InitLauncher(javaw);
208 DumpState();
209 if (JLI_IsTraceLauncher()) {
210 int i;
211 printf("Command line args:\n");
212 for (i = 0; i < argc ; i++) {
213 printf("argv[%d] = %s\n", i, argv[i]);
214 }
215 AddOption("-Dsun.java.launcher.diag=true", NULL);
216 }
217
218 /*
219 * Make sure the specified version of the JRE is running.
220 *
221 * There are three things to note about the SelectVersion() routine:
222 * 1) If the version running isn't correct, this routine doesn't
223 * return (either the correct version has been exec'd or an error
224 * was issued).
225 * 2) Argc and Argv in this scope are *not* altered by this routine.
226 * It is the responsibility of subsequent code to ignore the
227 * arguments handled by this routine.
228 * 3) As a side-effect, the variable "main_class" is guaranteed to
229 * be set (if it should ever be set). This isn't exactly the
230 * poster child for structured programming, but it is a small
231 * price to pay for not processing a jar file operand twice.
232 * (Note: This side effect has been disabled. See comment on
233 * bugid 5030265 below.)
234 */
235 SelectVersion(argc, argv, &main_class);
236
237 CreateExecutionEnvironment(&argc, &argv,
238 jrepath, sizeof(jrepath),
239 jvmpath, sizeof(jvmpath),
240 jvmcfg, sizeof(jvmcfg));
241
242 if (!IsJavaArgs()) {
243 SetJvmEnvironment(argc,argv);
244 }
245
246 ifn.CreateJavaVM = 0;
247 ifn.GetDefaultJavaVMInitArgs = 0;
248
249 if (JLI_IsTraceLauncher()) {
250 start = CounterGet();
251 }
252
253 if (!LoadJavaVM(jvmpath, &ifn)) {
812 - 2 /* strlen("%s") */
813 + JLI_StrLen(s));
814 sprintf(def, format, s);
815 AddOption(def, NULL);
816 if (s != orig)
817 JLI_MemFree((char *) s);
818 }
819
820 /*
821 * The SelectVersion() routine ensures that an appropriate version of
822 * the JRE is running. The specification for the appropriate version
823 * is obtained from either the manifest of a jar file (preferred) or
824 * from command line options.
825 * The routine also parses splash screen command line options and
826 * passes on their values in private environment variables.
827 */
828 static void
829 SelectVersion(int argc, char **argv, char **main_class)
830 {
831 char *arg;
832 char **new_argv;
833 char **new_argp;
834 char *operand;
835 char *version = NULL;
836 char *jre = NULL;
837 int jarflag = 0;
838 int headlessflag = 0;
839 int restrict_search = -1; /* -1 implies not known */
840 manifest_info info;
841 char env_entry[MAXNAMELEN + 24] = ENV_ENTRY "=";
842 char *splash_file_name = NULL;
843 char *splash_jar_name = NULL;
844 char *env_in;
845 int res;
846
847 /*
848 * If the version has already been selected, set *main_class
849 * with the value passed through the environment (if any) and
850 * simply return.
851 */
852 if ((env_in = getenv(ENV_ENTRY)) != NULL) {
853 if (*env_in != '\0')
854 *main_class = JLI_StringDup(env_in);
855 return;
856 }
857
858 /*
859 * Scan through the arguments for options relevant to multiple JRE
860 * support. For reference, the command line syntax is defined as:
861 *
862 * SYNOPSIS
863 * java [options] class [argument...]
864 *
865 * java [options] -jar file.jar [argument...]
866 *
867 * As the scan is performed, make a copy of the argument list with
868 * the version specification options (new to 1.5) removed, so that
869 * a version less than 1.5 can be exec'd.
870 *
871 * Note that due to the syntax of the native Windows interface
872 * CreateProcess(), processing similar to the following exists in
873 * the Windows platform specific routine ExecJRE (in java_md.c).
874 * Changes here should be reproduced there.
875 */
876 new_argv = JLI_MemAlloc((argc + 1) * sizeof(char*));
877 new_argv[0] = argv[0];
878 new_argp = &new_argv[1];
879 argc--;
880 argv++;
881 while ((arg = *argv) != 0 && *arg == '-') {
882 if (JLI_StrCCmp(arg, "-version:") == 0) {
883 version = arg + 9;
884 } else if (JLI_StrCmp(arg, "-jre-restrict-search") == 0) {
885 restrict_search = 1;
886 } else if (JLI_StrCmp(arg, "-no-jre-restrict-search") == 0) {
887 restrict_search = 0;
888 } else {
889 if (JLI_StrCmp(arg, "-jar") == 0)
890 jarflag = 1;
891 /* deal with "unfortunate" classpath syntax */
892 if ((JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) &&
893 (argc >= 2)) {
894 *new_argp++ = arg;
895 argc--;
896 argv++;
897 arg = *argv;
898 }
899
900 /*
901 * Checking for headless toolkit option in the some way as AWT does:
902 * "true" means true and any other value means false
903 */
904 if (JLI_StrCmp(arg, "-Djava.awt.headless=true") == 0) {
905 headlessflag = 1;
906 } else if (JLI_StrCCmp(arg, "-Djava.awt.headless=") == 0) {
907 headlessflag = 0;
908 } else if (JLI_StrCCmp(arg, "-splash:") == 0) {
909 splash_file_name = arg+8;
910 }
911 *new_argp++ = arg;
912 }
913 argc--;
914 argv++;
915 }
916 if (argc <= 0) { /* No operand? Possibly legit with -[full]version */
917 operand = NULL;
918 } else {
919 argc--;
920 *new_argp++ = operand = *argv++;
921 }
922 while (argc-- > 0) /* Copy over [argument...] */
923 *new_argp++ = *argv++;
924 *new_argp = NULL;
925
926 /*
927 * If there is a jar file, read the manifest. If the jarfile can't be
928 * read, the manifest can't be read from the jar file, or the manifest
929 * is corrupt, issue the appropriate error messages and exit.
930 *
931 * Even if there isn't a jar file, construct a manifest_info structure
932 * containing the command line information. It's a convenient way to carry
933 * this data around.
934 */
935 if (jarflag && operand) {
936 if ((res = JLI_ParseManifest(operand, &info)) != 0) {
937 if (res == -1)
938 JLI_ReportErrorMessage(JAR_ERROR2, operand);
939 else
940 JLI_ReportErrorMessage(JAR_ERROR3, operand);
941 exit(1);
942 }
943
944 /*
957 info.jre_version = NULL;
958 info.jre_restrict_search = 0;
959 }
960
961 /*
962 * Passing on splash screen info in environment variables
963 */
964 if (splash_file_name && !headlessflag) {
965 char* splash_file_entry = JLI_MemAlloc(JLI_StrLen(SPLASH_FILE_ENV_ENTRY "=")+JLI_StrLen(splash_file_name)+1);
966 JLI_StrCpy(splash_file_entry, SPLASH_FILE_ENV_ENTRY "=");
967 JLI_StrCat(splash_file_entry, splash_file_name);
968 putenv(splash_file_entry);
969 }
970 if (splash_jar_name && !headlessflag) {
971 char* splash_jar_entry = JLI_MemAlloc(JLI_StrLen(SPLASH_JAR_ENV_ENTRY "=")+JLI_StrLen(splash_jar_name)+1);
972 JLI_StrCpy(splash_jar_entry, SPLASH_JAR_ENV_ENTRY "=");
973 JLI_StrCat(splash_jar_entry, splash_jar_name);
974 putenv(splash_jar_entry);
975 }
976
977 /*
978 * The JRE-Version and JRE-Restrict-Search values (if any) from the
979 * manifest are overwritten by any specified on the command line.
980 */
981 if (version != NULL)
982 info.jre_version = version;
983 if (restrict_search != -1)
984 info.jre_restrict_search = restrict_search;
985
986 /*
987 * "Valid" returns (other than unrecoverable errors) follow. Set
988 * main_class as a side-effect of this routine.
989 */
990 if (info.main_class != NULL)
991 *main_class = JLI_StringDup(info.main_class);
992
993 /*
994 * If no version selection information is found either on the command
995 * line or in the manifest, simply return.
996 */
997 if (info.jre_version == NULL) {
998 JLI_FreeManifest();
999 JLI_MemFree(new_argv);
1000 return;
1001 }
1002
1003 /*
1004 * Check for correct syntax of the version specification (JSR 56).
1005 */
1006 if (!JLI_ValidVersionString(info.jre_version)) {
1007 JLI_ReportErrorMessage(SPC_ERROR1, info.jre_version);
1008 exit(1);
1009 }
1010
1011 /*
1012 * Find the appropriate JVM on the system. Just to be as forgiving as
1013 * possible, if the standard algorithms don't locate an appropriate
1014 * jre, check to see if the one running will satisfy the requirements.
1015 * This can happen on systems which haven't been set-up for multiple
1016 * JRE support.
1017 */
1018 jre = LocateJRE(&info);
1019 JLI_TraceLauncher("JRE-Version = %s, JRE-Restrict-Search = %s Selected = %s\n",
1020 (info.jre_version?info.jre_version:"null"),
1021 (info.jre_restrict_search?"true":"false"), (jre?jre:"null"));
1022
1023 if (jre == NULL) {
1024 if (JLI_AcceptableRelease(GetFullVersion(), info.jre_version)) {
1025 JLI_FreeManifest();
1026 JLI_MemFree(new_argv);
1027 return;
1028 } else {
1029 JLI_ReportErrorMessage(CFG_ERROR4, info.jre_version);
1030 exit(1);
1031 }
1032 }
1033
1034 /*
1035 * If I'm not the chosen one, exec the chosen one. Returning from
1036 * ExecJRE indicates that I am indeed the chosen one.
1037 *
1038 * The private environment variable _JAVA_VERSION_SET is used to
1039 * prevent the chosen one from re-reading the manifest file and
1040 * using the values found within to override the (potential) command
1041 * line flags stripped from argv (because the target may not
1042 * understand them). Passing the MainClass value is an optimization
1043 * to avoid locating, expanding and parsing the manifest extra
1044 * times.
1045 */
1046 if (info.main_class != NULL) {
1047 if (JLI_StrLen(info.main_class) <= MAXNAMELEN) {
1048 (void)JLI_StrCat(env_entry, info.main_class);
1049 } else {
1050 JLI_ReportErrorMessage(CLS_ERROR5, MAXNAMELEN);
1051 exit(1);
1052 }
1053 }
1054 (void)putenv(env_entry);
1055 ExecJRE(jre, new_argv);
1056 JLI_FreeManifest();
1057 JLI_MemFree(new_argv);
1058 return;
1059 }
1060
1061 /*
1062 * Parses command line arguments. Returns JNI_FALSE if launcher
1063 * should exit without starting vm, returns JNI_TRUE if vm needs
1064 * to be started to process given options. *pret (the launcher
1065 * process return value) is set to 0 for a normal exit.
1066 */
1067 static jboolean
1068 ParseArguments(int *pargc, char ***pargv,
1069 int *pmode, char **pwhat,
1070 int *pret, const char *jrepath)
1071 {
1072 int argc = *pargc;
1073 char **argv = *pargv;
1074 int mode = LM_UNKNOWN;
1075 char *arg;
1076
1077 *pret = 0;
1078
1137 char *p = arg + 5;
1138 char *tmp = JLI_MemAlloc(JLI_StrLen(arg) + 50);
1139 if (*p) {
1140 sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1);
1141 } else {
1142 sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof");
1143 }
1144 AddOption(tmp, NULL);
1145 } else if (JLI_StrCCmp(arg, "-ss") == 0 ||
1146 JLI_StrCCmp(arg, "-oss") == 0 ||
1147 JLI_StrCCmp(arg, "-ms") == 0 ||
1148 JLI_StrCCmp(arg, "-mx") == 0) {
1149 char *tmp = JLI_MemAlloc(JLI_StrLen(arg) + 6);
1150 sprintf(tmp, "-X%s", arg + 1); /* skip '-' */
1151 AddOption(tmp, NULL);
1152 } else if (JLI_StrCmp(arg, "-checksource") == 0 ||
1153 JLI_StrCmp(arg, "-cs") == 0 ||
1154 JLI_StrCmp(arg, "-noasyncgc") == 0) {
1155 /* No longer supported */
1156 JLI_ReportErrorMessage(ARG_WARN, arg);
1157 } else if (JLI_StrCCmp(arg, "-version:") == 0 ||
1158 JLI_StrCmp(arg, "-no-jre-restrict-search") == 0 ||
1159 JLI_StrCmp(arg, "-jre-restrict-search") == 0 ||
1160 JLI_StrCCmp(arg, "-splash:") == 0) {
1161 ; /* Ignore machine independent options already handled */
1162 } else if (ProcessPlatformOption(arg)) {
1163 ; /* Processing of platform dependent options */
1164 } else if (RemovableOption(arg)) {
1165 ; /* Do not pass option to vm. */
1166 } else {
1167 AddOption(arg, NULL);
1168 }
1169 }
1170
1171 if (--argc >= 0) {
1172 *pwhat = *argv++;
1173 }
1174
1175 if (*pwhat == NULL) {
1176 *pret = 1;
1177 } else if (mode == LM_UNKNOWN) {
1178 /* default to LM_CLASS if -jar and -cp option are
1179 * not specified */
1180 mode = LM_CLASS;
|
199 _fVersion = fullversion;
200 _dVersion = dotversion;
201 _launcher_name = lname;
202 _program_name = pname;
203 _is_java_args = javaargs;
204 _wc_enabled = cpwildcard;
205 _ergo_policy = ergo;
206
207 InitLauncher(javaw);
208 DumpState();
209 if (JLI_IsTraceLauncher()) {
210 int i;
211 printf("Command line args:\n");
212 for (i = 0; i < argc ; i++) {
213 printf("argv[%d] = %s\n", i, argv[i]);
214 }
215 AddOption("-Dsun.java.launcher.diag=true", NULL);
216 }
217
218 /*
219 * SelectVersion() has several responsibilities:
220 *
221 * 1) Disallow specification of another JRE. With 1.9, another
222 * version of the JRE cannot be invoked.
223 * 2) Allow for a JRE version to invoke JDK 1.9 or later. Since
224 * all mJRE directives have been stripped from the request but
225 * the pre 1.9 JRE [ 1.6 thru 1.8 ], it is as if 1.9+ has been
226 * invoked from the command line.
227 */
228 SelectVersion(argc, argv, &main_class);
229
230 CreateExecutionEnvironment(&argc, &argv,
231 jrepath, sizeof(jrepath),
232 jvmpath, sizeof(jvmpath),
233 jvmcfg, sizeof(jvmcfg));
234
235 if (!IsJavaArgs()) {
236 SetJvmEnvironment(argc,argv);
237 }
238
239 ifn.CreateJavaVM = 0;
240 ifn.GetDefaultJavaVMInitArgs = 0;
241
242 if (JLI_IsTraceLauncher()) {
243 start = CounterGet();
244 }
245
246 if (!LoadJavaVM(jvmpath, &ifn)) {
805 - 2 /* strlen("%s") */
806 + JLI_StrLen(s));
807 sprintf(def, format, s);
808 AddOption(def, NULL);
809 if (s != orig)
810 JLI_MemFree((char *) s);
811 }
812
813 /*
814 * The SelectVersion() routine ensures that an appropriate version of
815 * the JRE is running. The specification for the appropriate version
816 * is obtained from either the manifest of a jar file (preferred) or
817 * from command line options.
818 * The routine also parses splash screen command line options and
819 * passes on their values in private environment variables.
820 */
821 static void
822 SelectVersion(int argc, char **argv, char **main_class)
823 {
824 char *arg;
825 char *operand;
826 char *version = NULL;
827 char *jre = NULL;
828 int jarflag = 0;
829 int headlessflag = 0;
830 int restrict_search = -1; /* -1 implies not known */
831 manifest_info info;
832 char env_entry[MAXNAMELEN + 24] = ENV_ENTRY "=";
833 char *splash_file_name = NULL;
834 char *splash_jar_name = NULL;
835 char *env_in;
836 int res;
837
838 /*
839 * If the version has already been selected, set *main_class
840 * with the value passed through the environment (if any) and
841 * simply return.
842 */
843
844 /*
845 * This environmental variable can be set by mJRE capable JREs
846 * [ 1.5 thru 1.8 ]. All other aspects of mJRE processing have been
847 * stripped by those JREs. This environmental variable allows 1.9+
848 * JREs to be started by these mJRE capable JREs.
849 * Note that mJRE directives in the jar manifest file would have been
850 * ignored for a JRE started by another JRE...
851 * .. skipped for JRE 1.5 and beyond.
852 * .. not even checked for pre 1.5.
853 */
854 if ((env_in = getenv(ENV_ENTRY)) != NULL) {
855 if (*env_in != '\0')
856 *main_class = JLI_StringDup(env_in);
857 return;
858 }
859
860 /*
861 * Scan through the arguments for options relevant to multiple JRE
862 * support. Multiple JRE support existed in JRE versions 1.5 thru 1.8.
863 *
864 * This capability is no longer available with JRE versions 1.9 and later.
865 * These command line options are reported as errors.
866 */
867 argc--;
868 argv++;
869 while ((arg = *argv) != 0 && *arg == '-') {
870 if (JLI_StrCCmp(arg, "-version:") == 0) {
871 JLI_ReportErrorMessage(SPC_ERROR1);
872 } else if (JLI_StrCmp(arg, "-jre-restrict-search") == 0) {
873 JLI_ReportErrorMessage(SPC_ERROR2);
874 } else if (JLI_StrCmp(arg, "-jre-no-restrict-search") == 0) {
875 JLI_ReportErrorMessage(SPC_ERROR2);
876 } else {
877 if (JLI_StrCmp(arg, "-jar") == 0)
878 jarflag = 1;
879 /* deal with "unfortunate" classpath syntax */
880 if ((JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) &&
881 (argc >= 2)) {
882 argc--;
883 argv++;
884 arg = *argv;
885 }
886
887 /*
888 * Checking for headless toolkit option in the some way as AWT does:
889 * "true" means true and any other value means false
890 */
891 if (JLI_StrCmp(arg, "-Djava.awt.headless=true") == 0) {
892 headlessflag = 1;
893 } else if (JLI_StrCCmp(arg, "-Djava.awt.headless=") == 0) {
894 headlessflag = 0;
895 } else if (JLI_StrCCmp(arg, "-splash:") == 0) {
896 splash_file_name = arg+8;
897 }
898 }
899 argc--;
900 argv++;
901 }
902 if (argc <= 0) { /* No operand? Possibly legit with -[full]version */
903 operand = NULL;
904 } else {
905 argc--;
906 operand = *argv++;
907 }
908
909 /*
910 * If there is a jar file, read the manifest. If the jarfile can't be
911 * read, the manifest can't be read from the jar file, or the manifest
912 * is corrupt, issue the appropriate error messages and exit.
913 *
914 * Even if there isn't a jar file, construct a manifest_info structure
915 * containing the command line information. It's a convenient way to carry
916 * this data around.
917 */
918 if (jarflag && operand) {
919 if ((res = JLI_ParseManifest(operand, &info)) != 0) {
920 if (res == -1)
921 JLI_ReportErrorMessage(JAR_ERROR2, operand);
922 else
923 JLI_ReportErrorMessage(JAR_ERROR3, operand);
924 exit(1);
925 }
926
927 /*
940 info.jre_version = NULL;
941 info.jre_restrict_search = 0;
942 }
943
944 /*
945 * Passing on splash screen info in environment variables
946 */
947 if (splash_file_name && !headlessflag) {
948 char* splash_file_entry = JLI_MemAlloc(JLI_StrLen(SPLASH_FILE_ENV_ENTRY "=")+JLI_StrLen(splash_file_name)+1);
949 JLI_StrCpy(splash_file_entry, SPLASH_FILE_ENV_ENTRY "=");
950 JLI_StrCat(splash_file_entry, splash_file_name);
951 putenv(splash_file_entry);
952 }
953 if (splash_jar_name && !headlessflag) {
954 char* splash_jar_entry = JLI_MemAlloc(JLI_StrLen(SPLASH_JAR_ENV_ENTRY "=")+JLI_StrLen(splash_jar_name)+1);
955 JLI_StrCpy(splash_jar_entry, SPLASH_JAR_ENV_ENTRY "=");
956 JLI_StrCat(splash_jar_entry, splash_jar_name);
957 putenv(splash_jar_entry);
958 }
959
960
961 /*
962 * "Valid" returns (other than unrecoverable errors) follow. Set
963 * main_class as a side-effect of this routine.
964 */
965 if (info.main_class != NULL)
966 *main_class = JLI_StringDup(info.main_class);
967
968 if (info.jre_version == NULL) {
969 JLI_FreeManifest();
970 return;
971 }
972
973 }
974
975 /*
976 * Parses command line arguments. Returns JNI_FALSE if launcher
977 * should exit without starting vm, returns JNI_TRUE if vm needs
978 * to be started to process given options. *pret (the launcher
979 * process return value) is set to 0 for a normal exit.
980 */
981 static jboolean
982 ParseArguments(int *pargc, char ***pargv,
983 int *pmode, char **pwhat,
984 int *pret, const char *jrepath)
985 {
986 int argc = *pargc;
987 char **argv = *pargv;
988 int mode = LM_UNKNOWN;
989 char *arg;
990
991 *pret = 0;
992
1051 char *p = arg + 5;
1052 char *tmp = JLI_MemAlloc(JLI_StrLen(arg) + 50);
1053 if (*p) {
1054 sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1);
1055 } else {
1056 sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof");
1057 }
1058 AddOption(tmp, NULL);
1059 } else if (JLI_StrCCmp(arg, "-ss") == 0 ||
1060 JLI_StrCCmp(arg, "-oss") == 0 ||
1061 JLI_StrCCmp(arg, "-ms") == 0 ||
1062 JLI_StrCCmp(arg, "-mx") == 0) {
1063 char *tmp = JLI_MemAlloc(JLI_StrLen(arg) + 6);
1064 sprintf(tmp, "-X%s", arg + 1); /* skip '-' */
1065 AddOption(tmp, NULL);
1066 } else if (JLI_StrCmp(arg, "-checksource") == 0 ||
1067 JLI_StrCmp(arg, "-cs") == 0 ||
1068 JLI_StrCmp(arg, "-noasyncgc") == 0) {
1069 /* No longer supported */
1070 JLI_ReportErrorMessage(ARG_WARN, arg);
1071 } else if (JLI_StrCCmp(arg, "-splash:") == 0) {
1072 ; /* Ignore machine independent options already handled */
1073 } else if (ProcessPlatformOption(arg)) {
1074 ; /* Processing of platform dependent options */
1075 } else if (RemovableOption(arg)) {
1076 ; /* Do not pass option to vm. */
1077 } else {
1078 AddOption(arg, NULL);
1079 }
1080 }
1081
1082 if (--argc >= 0) {
1083 *pwhat = *argv++;
1084 }
1085
1086 if (*pwhat == NULL) {
1087 *pret = 1;
1088 } else if (mode == LM_UNKNOWN) {
1089 /* default to LM_CLASS if -jar and -cp option are
1090 * not specified */
1091 mode = LM_CLASS;
|