source: trunk/icedtea-web/launcher/java_md.c@ 350

Last change on this file since 350 was 348, checked in by dmik, 13 years ago

vendor: Add icedtea-web v1.1.2 to current.

File size: 55.4 KB
Line 
1/*
2 * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26#include "java.h"
27#include <dirent.h>
28#include <dlfcn.h>
29#include <fcntl.h>
30#include <inttypes.h>
31#include <stdio.h>
32#include <string.h>
33#include <stdlib.h>
34#include <sys/stat.h>
35#include <unistd.h>
36#include <sys/types.h>
37#include "manifest_info.h"
38#include "version_comp.h"
39
40#ifdef __linux__
41#include <pthread.h>
42#else
43#include <thread.h>
44#endif
45
46#define JVM_DLL "libjvm.so"
47#define JAVA_DLL "libjava.so"
48
49/*
50 * If a processor / os combination has the ability to run binaries of
51 * two data models and cohabitation of jre/jdk bits with both data
52 * models is supported, then DUAL_MODE is defined. When DUAL_MODE is
53 * defined, the architecture names for the narrow and wide version of
54 * the architecture are defined in LIBARCH64NAME and LIBARCH32NAME. Currently
55 * only Solaris on sparc/sparcv9 and i586/amd64 is DUAL_MODE; linux
56 * i586/amd64 could be defined as DUAL_MODE but that is not the
57 * current policy.
58 */
59
60#ifndef LIBARCHNAME
61# error "The macro LIBARCHNAME was not defined on the compile line"
62#endif
63
64#ifdef __sun
65# define DUAL_MODE
66# ifndef LIBARCH32NAME
67# error "The macro LIBARCH32NAME was not defined on the compile line"
68# endif
69# ifndef LIBARCH64NAME
70# error "The macro LIBARCH64NAME was not defined on the compile line"
71# endif
72# include <sys/systeminfo.h>
73# include <sys/elf.h>
74# include <stdio.h>
75#endif
76
77/* pointer to environment */
78extern char **environ;
79
80/*
81 * A collection of useful strings. One should think of these as #define
82 * entries, but actual strings can be more efficient (with many compilers).
83 */
84#ifdef __linux__
85static const char *system_dir = "/usr/java";
86static const char *user_dir = "/java";
87#else /* Solaris */
88static const char *system_dir = "/usr/jdk";
89static const char *user_dir = "/jdk";
90#endif
91
92/*
93 * Flowchart of launcher execs and options processing on unix
94 *
95 * The selection of the proper vm shared library to open depends on
96 * several classes of command line options, including vm "flavor"
97 * options (-client, -server) and the data model options, -d32 and
98 * -d64, as well as a version specification which may have come from
99 * the command line or from the manifest of an executable jar file.
100 * The vm selection options are not passed to the running
101 * virtual machine; they must be screened out by the launcher.
102 *
103 * The version specification (if any) is processed first by the
104 * platform independent routine SelectVersion. This may result in
105 * the exec of the specified launcher version.
106 *
107 * Typically, the launcher execs at least once to ensure a suitable
108 * LD_LIBRARY_PATH is in effect for the process. The first exec
109 * screens out all the data model options; leaving the choice of data
110 * model implicit in the binary selected to run. However, in case no
111 * exec is done, the data model options are screened out before the vm
112 * is invoked.
113 *
114 * incoming argv ------------------------------
115 * | |
116 * \|/ |
117 * CheckJVMType |
118 * (removes -client, -server, etc.) |
119 * \|/
120 * CreateExecutionEnvironment
121 * (removes -d32 and -d64,
122 * determines desired data model,
123 * sets up LD_LIBRARY_PATH,
124 * and exec's)
125 * |
126 * --------------------------------------------
127 * |
128 * \|/
129 * exec child 1 incoming argv -----------------
130 * | |
131 * \|/ |
132 * CheckJVMType |
133 * (removes -client, -server, etc.) |
134 * | \|/
135 * | CreateExecutionEnvironment
136 * | (verifies desired data model
137 * | is running and acceptable
138 * | LD_LIBRARY_PATH;
139 * | no-op in child)
140 * |
141 * \|/
142 * TranslateDashJArgs...
143 * (Prepare to pass args to vm)
144 * |
145 * |
146 * |
147 * \|/
148 * ParseArguments
149 * (ignores -d32 and -d64,
150 * processes version options,
151 * creates argument list for vm,
152 * etc.)
153 *
154 */
155
156static char *SetExecname(char **argv);
157static char * GetExecname();
158static jboolean GetJVMPath(const char *jrepath, const char *jvmtype,
159 char *jvmpath, jint jvmpathsize, char * arch);
160static jboolean GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative);
161static jboolean GetIcedTeaWebJREPath(char *path, jint pathsize, char * arch, jboolean speculative);
162
163const char *
164GetArch()
165{
166 return LIBARCHNAME;
167}
168
169void
170CreateExecutionEnvironment(int *_argcp,
171 char ***_argvp,
172 char jrepath[],
173 jint so_jrepath,
174 char jvmpath[],
175 jint so_jvmpath,
176 char **original_argv) {
177 /*
178 * First, determine if we are running the desired data model. If we
179 * are running the desired data model, all the error messages
180 * associated with calling GetJREPath, ReadKnownVMs, etc. should be
181 * output. However, if we are not running the desired data model,
182 * some of the errors should be suppressed since it is more
183 * informative to issue an error message based on whether or not the
184 * os/processor combination has dual mode capabilities.
185 */
186
187 char *execname = NULL;
188 int original_argc = *_argcp;
189 jboolean jvmpathExists;
190
191 /* Compute the name of the executable */
192 execname = SetExecname(*_argvp);
193
194 /* Set the LD_LIBRARY_PATH environment variable, check data model
195 flags, and exec process, if needed */
196 {
197 char *arch = (char *)GetArch(); /* like sparc or sparcv9 */
198 char * jvmtype = NULL;
199 int argc = *_argcp;
200 char **argv = original_argv;
201
202 char *runpath = NULL; /* existing effective LD_LIBRARY_PATH
203 setting */
204
205 int running = CURRENT_DATA_MODEL;
206
207 int wanted = running; /* What data mode is being
208 asked for? Current model is
209 fine unless another model
210 is asked for */
211
212 char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */
213 char* newpath = NULL; /* path on new LD_LIBRARY_PATH */
214 char* lastslash = NULL;
215
216 char** newenvp = NULL; /* current environment */
217
218 char** newargv = NULL;
219 int newargc = 0;
220#ifdef __sun
221 char* dmpath = NULL; /* data model specific LD_LIBRARY_PATH,
222 Solaris only */
223#endif
224
225 /*
226 * Starting in 1.5, all unix platforms accept the -d32 and -d64
227 * options. On platforms where only one data-model is supported
228 * (e.g. ia-64 Linux), using the flag for the other data model is
229 * an error and will terminate the program.
230 */
231
232 { /* open new scope to declare local variables */
233 int i;
234
235 newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(*newargv));
236 newargv[newargc++] = argv[0];
237
238 /* scan for data model arguments and remove from argument list;
239 last occurrence determines desired data model */
240 for (i=1; i < argc; i++) {
241
242 if (strcmp(argv[i], "-J-d64") == 0 || strcmp(argv[i], "-d64") == 0) {
243 wanted = 64;
244 continue;
245 }
246 if (strcmp(argv[i], "-J-d32") == 0 || strcmp(argv[i], "-d32") == 0) {
247 wanted = 32;
248 continue;
249 }
250 newargv[newargc++] = argv[i];
251
252#ifdef JAVA_ARGS
253 if (argv[i][0] != '-')
254 continue;
255#else
256 if (strcmp(argv[i], "-classpath") == 0 || strcmp(argv[i], "-cp") == 0) {
257 i++;
258 if (i >= argc) break;
259 newargv[newargc++] = argv[i];
260 continue;
261 }
262 if (argv[i][0] != '-') { i++; break; }
263#endif
264 }
265
266 /* copy rest of args [i .. argc) */
267 while (i < argc) {
268 newargv[newargc++] = argv[i++];
269 }
270 newargv[newargc] = NULL;
271
272 /*
273 * newargv has all proper arguments here
274 */
275
276 argc = newargc;
277 argv = newargv;
278 }
279
280 /* If the data model is not changing, it is an error if the
281 jvmpath does not exist */
282 if (wanted == running) {
283 /* Find out where the JRE is that we will be using. */
284 if (!GetIcedTeaWebJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) {
285 fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n");
286 exit(2);
287 }
288
289 /* Find the specified JVM type */
290 if (ReadKnownVMs(jrepath, arch, JNI_FALSE) < 1) {
291 fprintf(stderr, "Error: no known VMs. (check for corrupt jvm.cfg file)\n");
292 exit(1);
293 }
294
295 jvmpath[0] = '\0';
296 jvmtype = CheckJvmType(_argcp, _argvp, JNI_FALSE);
297
298 if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch )) {
299 fprintf(stderr, "Error: no `%s' JVM at `%s'.\n", jvmtype, jvmpath);
300 exit(4);
301 }
302 } else { /* do the same speculatively or exit */
303#ifdef DUAL_MODE
304 if (running != wanted) {
305 /* Find out where the JRE is that we will be using. */
306 if (!GetJREPath(jrepath, so_jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE)) {
307 goto EndDataModelSpeculate;
308 }
309
310 /*
311 * Read in jvm.cfg for target data model and process vm
312 * selection options.
313 */
314 if (ReadKnownVMs(jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE) < 1) {
315 goto EndDataModelSpeculate;
316 }
317 jvmpath[0] = '\0';
318 jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE);
319 /* exec child can do error checking on the existence of the path */
320 jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath,
321 ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME));
322
323 }
324 EndDataModelSpeculate: /* give up and let other code report error message */
325 ;
326#else
327 fprintf(stderr, "This Java instance does not support a %d-bit JVM.\nPlease install the desired version.\n", wanted);
328 exit(1);
329#endif
330 }
331
332 /*
333 * We will set the LD_LIBRARY_PATH as follows:
334 *
335 * o $JVMPATH (directory portion only)
336 * o $JRE/lib/$LIBARCHNAME
337 * o $JRE/../lib/$LIBARCHNAME
338 *
339 * followed by the user's previous effective LD_LIBRARY_PATH, if
340 * any.
341 */
342
343#ifdef __sun
344 /*
345 * Starting in Solaris 7, ld.so.1 supports three LD_LIBRARY_PATH
346 * variables:
347 *
348 * 1. LD_LIBRARY_PATH -- used for 32 and 64 bit searches if
349 * data-model specific variables are not set.
350 *
351 * 2. LD_LIBRARY_PATH_64 -- overrides and replaces LD_LIBRARY_PATH
352 * for 64-bit binaries.
353 *
354 * 3. LD_LIBRARY_PATH_32 -- overrides and replaces LD_LIBRARY_PATH
355 * for 32-bit binaries.
356 *
357 * The vm uses LD_LIBRARY_PATH to set the java.library.path system
358 * property. To shield the vm from the complication of multiple
359 * LD_LIBRARY_PATH variables, if the appropriate data model
360 * specific variable is set, we will act as if LD_LIBRARY_PATH had
361 * the value of the data model specific variant and the data model
362 * specific variant will be unset. Note that the variable for the
363 * *wanted* data model must be used (if it is set), not simply the
364 * current running data model.
365 */
366
367 switch(wanted) {
368 case 0:
369 if(running == 32) {
370 dmpath = getenv("LD_LIBRARY_PATH_32");
371 wanted = 32;
372 }
373 else {
374 dmpath = getenv("LD_LIBRARY_PATH_64");
375 wanted = 64;
376 }
377 break;
378
379 case 32:
380 dmpath = getenv("LD_LIBRARY_PATH_32");
381 break;
382
383 case 64:
384 dmpath = getenv("LD_LIBRARY_PATH_64");
385 break;
386
387 default:
388 fprintf(stderr, "Improper value at line %d.", __LINE__);
389 exit(1); /* unknown value in wanted */
390 break;
391 }
392
393 /*
394 * If dmpath is NULL, the relevant data model specific variable is
395 * not set and normal LD_LIBRARY_PATH should be used.
396 */
397 if( dmpath == NULL) {
398 runpath = getenv("LD_LIBRARY_PATH");
399 }
400 else {
401 runpath = dmpath;
402 }
403#else
404 /*
405 * If not on Solaris, assume only a single LD_LIBRARY_PATH
406 * variable.
407 */
408 runpath = getenv("LD_LIBRARY_PATH");
409#endif /* __sun */
410
411#ifdef __linux
412 /*
413 * On linux, if a binary is running as sgid or suid, glibc sets
414 * LD_LIBRARY_PATH to the empty string for security purposes. (In
415 * contrast, on Solaris the LD_LIBRARY_PATH variable for a
416 * privileged binary does not lose its settings; but the dynamic
417 * linker does apply more scrutiny to the path.) The launcher uses
418 * the value of LD_LIBRARY_PATH to prevent an exec loop.
419 * Therefore, if we are running sgid or suid, this function's
420 * setting of LD_LIBRARY_PATH will be ineffective and we should
421 * return from the function now. Getting the right libraries to
422 * be found must be handled through other mechanisms.
423 */
424 if((getgid() != getegid()) || (getuid() != geteuid()) ) {
425 return;
426 }
427#endif
428
429 /* runpath contains current effective LD_LIBRARY_PATH setting */
430
431 jvmpath = JLI_StringDup(jvmpath);
432 new_runpath = JLI_MemAlloc( ((runpath!=NULL)?strlen(runpath):0) +
433 2*strlen(jrepath) + 2*strlen(arch) +
434 strlen(jvmpath) + 52);
435 newpath = new_runpath + strlen("LD_LIBRARY_PATH=");
436
437
438 /*
439 * Create desired LD_LIBRARY_PATH value for target data model.
440 */
441 {
442 /* remove the name of the .so from the JVM path */
443 lastslash = strrchr(jvmpath, '/');
444 if (lastslash)
445 *lastslash = '\0';
446
447
448 /* jvmpath, ((running != wanted)?((wanted==64)?"/"LIBARCH64NAME:"/.."):""), */
449
450 sprintf(new_runpath, "LD_LIBRARY_PATH="
451 "%s:"
452 "%s/lib/%s:"
453 "%s/../lib/%s",
454 jvmpath,
455#ifdef DUAL_MODE
456 jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME),
457 jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME)
458#else
459 jrepath, arch,
460 jrepath, arch
461#endif
462 );
463
464
465 /*
466 * Check to make sure that the prefix of the current path is the
467 * desired environment variable setting.
468 */
469 if (runpath != NULL &&
470 strncmp(newpath, runpath, strlen(newpath))==0 &&
471 (runpath[strlen(newpath)] == 0 || runpath[strlen(newpath)] == ':') &&
472 (running == wanted) /* data model does not have to be changed */
473#ifdef __sun
474 && (dmpath == NULL) /* data model specific variables not set */
475#endif
476 ) {
477
478 return;
479
480 }
481 }
482
483 /*
484 * Place the desired environment setting onto the prefix of
485 * LD_LIBRARY_PATH. Note that this prevents any possible infinite
486 * loop of execv() because we test for the prefix, above.
487 */
488 if (runpath != 0 && (runpath[0] != '\0')) {
489 strcat(new_runpath, ":");
490 strcat(new_runpath, runpath);
491 }
492
493 if( putenv(new_runpath) != 0) {
494 exit(1); /* problem allocating memory; LD_LIBRARY_PATH not set
495 properly */
496 }
497
498 /*
499 * Unix systems document that they look at LD_LIBRARY_PATH only
500 * once at startup, so we have to re-exec the current executable
501 * to get the changed environment variable to have an effect.
502 */
503
504#ifdef __sun
505 /*
506 * If dmpath is not NULL, remove the data model specific string
507 * in the environment for the exec'ed child.
508 */
509
510 if( dmpath != NULL)
511 (void)UnsetEnv((wanted==32)?"LD_LIBRARY_PATH_32":"LD_LIBRARY_PATH_64");
512#endif
513
514 newenvp = environ;
515
516 {
517 char *newexec = execname;
518#ifdef DUAL_MODE
519 /*
520 * If the data model is being changed, the path to the
521 * executable must be updated accordingly; the executable name
522 * and directory the executable resides in are separate. In the
523 * case of 32 => 64, the new bits are assumed to reside in, e.g.
524 * "olddir/LIBARCH64NAME/execname"; in the case of 64 => 32,
525 * the bits are assumed to be in "olddir/../execname". For example,
526 *
527 * olddir/sparcv9/execname
528 * olddir/amd64/execname
529 *
530 * for Solaris SPARC and Linux amd64, respectively.
531 */
532
533 if (running != wanted) {
534 char *oldexec = strcpy(JLI_MemAlloc(strlen(execname) + 1), execname);
535 char *olddir = oldexec;
536 char *oldbase = strrchr(oldexec, '/');
537
538
539 newexec = JLI_MemAlloc(strlen(execname) + 20);
540 *oldbase++ = 0;
541 sprintf(newexec, "%s/%s/%s", olddir,
542 ((wanted==64) ? LIBARCH64NAME : ".."), oldbase);
543 argv[0] = newexec;
544 }
545#endif
546
547 (void)fflush(stdout);
548 (void)fflush(stderr);
549 execve(newexec, argv, newenvp);
550 perror("execve()");
551
552 fprintf(stderr, "Error trying to exec %s.\n", newexec);
553 fprintf(stderr, "Check if file exists and permissions are set correctly.\n");
554
555#ifdef DUAL_MODE
556 if (running != wanted) {
557 fprintf(stderr, "Failed to start a %d-bit JVM process from a %d-bit JVM.\n",
558 wanted, running);
559# ifdef __sun
560
561# ifdef __sparc
562 fprintf(stderr, "Verify all necessary J2SE components have been installed.\n" );
563 fprintf(stderr,
564 "(Solaris SPARC 64-bit components must be installed after 32-bit components.)\n" );
565# else
566 fprintf(stderr, "Either 64-bit processes are not supported by this platform\n");
567 fprintf(stderr, "or the 64-bit components have not been installed.\n");
568# endif
569 }
570# endif
571#endif
572
573 }
574
575 exit(1);
576 }
577
578}
579
580
581/*
582 * On Solaris VM choosing is done by the launcher (java.c).
583 */
584static jboolean
585GetJVMPath(const char *jrepath, const char *jvmtype,
586 char *jvmpath, jint jvmpathsize, char * arch)
587{
588 struct stat s;
589
590 if (strchr(jvmtype, '/')) {
591 sprintf(jvmpath, "%s/" JVM_DLL, jvmtype);
592 } else {
593 sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
594 }
595 if (_launcher_debug)
596 printf("Does `%s' exist ... ", jvmpath);
597
598 if (stat(jvmpath, &s) == 0) {
599 if (_launcher_debug)
600 printf("yes.\n");
601 return JNI_TRUE;
602 } else {
603 if (_launcher_debug)
604 printf("no.\n");
605 return JNI_FALSE;
606 }
607}
608
609/*
610 * Find path to the JRE based on the the compile flag ICEDTEA_WEB_JRE
611 */
612static jboolean
613GetIcedTeaWebJREPath(char* path, jint pathsize, char* arch, jboolean speculative)
614{
615 char libjava[MAXPATHLEN];
616 snprintf(libjava, MAXPATHLEN, ICEDTEA_WEB_JRE "/lib/%s/" JAVA_DLL, arch);
617
618 if (_launcher_debug) {
619 printf(ICEDTEA_WEB_JRE "/lib/%s/" JAVA_DLL "\n", arch);
620 printf("libjava is %s\n", libjava);
621 }
622
623 if (access(libjava, F_OK) == 0) {
624 strncpy(path, ICEDTEA_WEB_JRE, pathsize);
625 goto found;
626 }
627
628 return JNI_FALSE;
629
630 found:
631 if (_launcher_debug)
632 printf("JRE path is %s\n", path);
633 return JNI_TRUE;
634}
635
636/*
637 * Find path to JRE based on .exe's location or registry settings.
638 */
639static jboolean
640GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative)
641{
642 char libjava[MAXPATHLEN];
643
644 if (GetApplicationHome(path, pathsize)) {
645 /* Is JRE co-located with the application? */
646 sprintf(libjava, "%s/lib/%s/" JAVA_DLL, path, arch);
647 if (access(libjava, F_OK) == 0) {
648 goto found;
649 }
650
651 /* Does the app ship a private JRE in <apphome>/jre directory? */
652 sprintf(libjava, "%s/jre/lib/%s/" JAVA_DLL, path, arch);
653 if (access(libjava, F_OK) == 0) {
654 strcat(path, "/jre");
655 goto found;
656 }
657 }
658
659 if (!speculative)
660 fprintf(stderr, "Error: could not find " JAVA_DLL "\n");
661 return JNI_FALSE;
662
663 found:
664 if (_launcher_debug)
665 printf("JRE path is %s\n", path);
666 return JNI_TRUE;
667}
668
669jboolean
670LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
671{
672 Dl_info dlinfo;
673 void *libjvm;
674
675 if (_launcher_debug) {
676 printf("JVM path is %s\n", jvmpath);
677 }
678
679 libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
680 if (libjvm == NULL) {
681#if defined(__solaris__) && defined(__sparc) && !defined(_LP64) /* i.e. 32-bit sparc */
682 FILE * fp;
683 Elf32_Ehdr elf_head;
684 int count;
685 int location;
686
687 fp = fopen(jvmpath, "r");
688 if(fp == NULL)
689 goto error;
690
691 /* read in elf header */
692 count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp);
693 fclose(fp);
694 if(count < 1)
695 goto error;
696
697 /*
698 * Check for running a server vm (compiled with -xarch=v8plus)
699 * on a stock v8 processor. In this case, the machine type in
700 * the elf header would not be included the architecture list
701 * provided by the isalist command, which is turn is gotten from
702 * sysinfo. This case cannot occur on 64-bit hardware and thus
703 * does not have to be checked for in binaries with an LP64 data
704 * model.
705 */
706 if(elf_head.e_machine == EM_SPARC32PLUS) {
707 char buf[257]; /* recommended buffer size from sysinfo man
708 page */
709 long length;
710 char* location;
711
712 length = sysinfo(SI_ISALIST, buf, 257);
713 if(length > 0) {
714 location = strstr(buf, "sparcv8plus ");
715 if(location == NULL) {
716 fprintf(stderr, "SPARC V8 processor detected; Server compiler requires V9 or better.\n");
717 fprintf(stderr, "Use Client compiler on V8 processors.\n");
718 fprintf(stderr, "Could not create the Java virtual machine.\n");
719 return JNI_FALSE;
720 }
721 }
722 }
723#endif
724 fprintf(stderr, "dl failure on line %d", __LINE__);
725 goto error;
726 }
727
728 ifn->CreateJavaVM = (CreateJavaVM_t)
729 dlsym(libjvm, "JNI_CreateJavaVM");
730 if (ifn->CreateJavaVM == NULL)
731 goto error;
732
733 ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
734 dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");
735 if (ifn->GetDefaultJavaVMInitArgs == NULL)
736 goto error;
737
738 return JNI_TRUE;
739
740error:
741 fprintf(stderr, "Error: failed %s, because %s\n", jvmpath, dlerror());
742 return JNI_FALSE;
743}
744
745/*
746 * If app is "/foo/bin/javac", or "/foo/bin/sparcv9/javac" then put
747 * "/foo" into buf.
748 */
749jboolean
750GetApplicationHome(char *buf, jint bufsize)
751{
752#ifdef __linux__
753 char *execname = GetExecname();
754 if (execname) {
755 strncpy(buf, execname, bufsize-1);
756 buf[bufsize-1] = '\0';
757 } else {
758 return JNI_FALSE;
759 }
760#else
761 Dl_info dlinfo;
762
763 dladdr((void *)GetApplicationHome, &dlinfo);
764 if (realpath(dlinfo.dli_fname, buf) == NULL) {
765 fprintf(stderr, "Error: realpath(`%s') failed.\n", dlinfo.dli_fname);
766 return JNI_FALSE;
767 }
768#endif
769
770 if (strrchr(buf, '/') == 0) {
771 buf[0] = '\0';
772 return JNI_FALSE;
773 }
774 *(strrchr(buf, '/')) = '\0'; /* executable file */
775 if (strlen(buf) < 4 || strrchr(buf, '/') == 0) {
776 buf[0] = '\0';
777 return JNI_FALSE;
778 }
779 if (strcmp("/bin", buf + strlen(buf) - 4) != 0)
780 *(strrchr(buf, '/')) = '\0'; /* sparcv9 or amd64 */
781 if (strlen(buf) < 4 || strcmp("/bin", buf + strlen(buf) - 4) != 0) {
782 buf[0] = '\0';
783 return JNI_FALSE;
784 }
785 *(strrchr(buf, '/')) = '\0'; /* bin */
786
787 return JNI_TRUE;
788}
789
790
791/*
792 * Return true if the named program exists
793 */
794static int
795ProgramExists(char *name)
796{
797 struct stat sb;
798 if (stat(name, &sb) != 0) return 0;
799 if (S_ISDIR(sb.st_mode)) return 0;
800 return (sb.st_mode & S_IEXEC) != 0;
801}
802
803
804/*
805 * Find a command in a directory, returning the path.
806 */
807static char *
808Resolve(char *indir, char *cmd)
809{
810 char name[PATH_MAX + 2], *real;
811
812 if ((strlen(indir) + strlen(cmd) + 1) > PATH_MAX) return 0;
813 sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd);
814 if (!ProgramExists(name)) return 0;
815 real = JLI_MemAlloc(PATH_MAX + 2);
816 if (!realpath(name, real))
817 strcpy(real, name);
818 return real;
819}
820
821
822/*
823 * Find a path for the executable
824 */
825static char *
826FindExecName(char *program)
827{
828 char cwdbuf[PATH_MAX+2];
829 char *path;
830 char *tmp_path;
831 char *f;
832 char *result = NULL;
833
834 /* absolute path? */
835 if (*program == FILE_SEPARATOR ||
836 (FILE_SEPARATOR=='\\' && strrchr(program, ':')))
837 return Resolve("", program+1);
838
839 /* relative path? */
840 if (strrchr(program, FILE_SEPARATOR) != 0) {
841 char buf[PATH_MAX+2];
842 return Resolve(getcwd(cwdbuf, sizeof(cwdbuf)), program);
843 }
844
845 /* from search path? */
846 path = getenv("PATH");
847 if (!path || !*path) path = ".";
848 tmp_path = JLI_MemAlloc(strlen(path) + 2);
849 strcpy(tmp_path, path);
850
851 for (f=tmp_path; *f && result==0; ) {
852 char *s = f;
853 while (*f && (*f != PATH_SEPARATOR)) ++f;
854 if (*f) *f++ = 0;
855 if (*s == FILE_SEPARATOR)
856 result = Resolve(s, program);
857 else {
858 /* relative path element */
859 char dir[2*PATH_MAX];
860 sprintf(dir, "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)),
861 FILE_SEPARATOR, s);
862 result = Resolve(dir, program);
863 }
864 if (result != 0) break;
865 }
866
867 JLI_MemFree(tmp_path);
868 return result;
869}
870
871
872/* Store the name of the executable once computed */
873static char *execname = NULL;
874
875/*
876 * Compute the name of the executable
877 *
878 * In order to re-exec securely we need the absolute path of the
879 * executable. On Solaris getexecname(3c) may not return an absolute
880 * path so we use dladdr to get the filename of the executable and
881 * then use realpath to derive an absolute path. From Solaris 9
882 * onwards the filename returned in DL_info structure from dladdr is
883 * an absolute pathname so technically realpath isn't required.
884 * On Linux we read the executable name from /proc/self/exe.
885 * As a fallback, and for platforms other than Solaris and Linux,
886 * we use FindExecName to compute the executable name.
887 */
888static char *
889SetExecname(char **argv)
890{
891 char* exec_path = NULL;
892
893 if (execname != NULL) /* Already determined */
894 return (execname);
895
896#if defined(__sun)
897 {
898 Dl_info dlinfo;
899 if (dladdr((void*)&SetExecname, &dlinfo)) {
900 char *resolved = (char*)JLI_MemAlloc(PATH_MAX+1);
901 if (resolved != NULL) {
902 exec_path = realpath(dlinfo.dli_fname, resolved);
903 if (exec_path == NULL) {
904 JLI_MemFree(resolved);
905 }
906 }
907 }
908 }
909#elif defined(__linux__)
910 {
911 const char* self = "/proc/self/exe";
912 char buf[PATH_MAX+1];
913 int len = readlink(self, buf, PATH_MAX);
914 if (len >= 0) {
915 buf[len] = '\0'; /* readlink doesn't nul terminate */
916 exec_path = JLI_StringDup(buf);
917 }
918 }
919#else /* !__sun && !__linux */
920 {
921 /* Not implemented */
922 }
923#endif
924
925 if (exec_path == NULL) {
926 exec_path = FindExecName(argv[0]);
927 }
928 execname = exec_path;
929 return exec_path;
930}
931
932/*
933 * Return the name of the executable. Used in java_md.c to find the JRE area.
934 */
935static char *
936GetExecname() {
937 return execname;
938}
939
940void ReportErrorMessage(char * message, jboolean always) {
941 if (always) {
942 fprintf(stderr, "%s\n", message);
943 }
944}
945
946void ReportErrorMessage2(char * format, char * string, jboolean always) {
947 if (always) {
948 fprintf(stderr, format, string);
949 fprintf(stderr, "\n");
950 }
951}
952
953void ReportExceptionDescription(JNIEnv * env) {
954 (*env)->ExceptionDescribe(env);
955}
956
957/*
958 * Return JNI_TRUE for an option string that has no effect but should
959 * _not_ be passed on to the vm; return JNI_FALSE otherwise. On
960 * Solaris SPARC, this screening needs to be done if:
961 * 1) LD_LIBRARY_PATH does _not_ need to be reset and
962 * 2) -d32 or -d64 is passed to a binary with a matching data model
963 * (the exec in SetLibraryPath removes -d<n> options and points the
964 * exec to the proper binary). When this exec is not done, these options
965 * would end up getting passed onto the vm.
966 */
967jboolean RemovableMachineDependentOption(char * option) {
968 /*
969 * Unconditionally remove both -d32 and -d64 options since only
970 * the last such options has an effect; e.g.
971 * java -d32 -d64 -d32 -version
972 * is equivalent to
973 * java -d32 -version
974 */
975
976 if( (strcmp(option, "-d32") == 0 ) ||
977 (strcmp(option, "-d64") == 0 ) )
978 return JNI_TRUE;
979 else
980 return JNI_FALSE;
981}
982
983/*
984 * The following methods (down to ServerClassMachine()) answer
985 * the question about whether a machine is a "server-class"
986 * machine. A server-class machine is loosely defined as one
987 * with 2 or more processors and 2 gigabytes or more physical
988 * memory. The definition of a processor is a physical package,
989 * not a hyperthreaded chip masquerading as a multi-processor.
990 * The definition of memory is also somewhat fuzzy, since x86
991 * machines seem not to report all the memory in their DIMMs, we
992 * think because of memory mapping of graphics cards, etc.
993 *
994 * This code is somewhat more confused with #ifdef's than we'd
995 * like because this file is used by both Solaris and Linux
996 * platforms, and so needs to be parameterized for SPARC and
997 * i586 hardware. The other Linux platforms (amd64 and ia64)
998 * don't even ask this question, because they only come with
999 * server JVMs. */
1000
1001# define KB (1024UL)
1002# define MB (1024UL * KB)
1003# define GB (1024UL * MB)
1004
1005/* Compute physical memory by asking the OS */
1006uint64_t
1007physical_memory(void) {
1008 const uint64_t pages = (uint64_t) sysconf(_SC_PHYS_PAGES);
1009 const uint64_t page_size = (uint64_t) sysconf(_SC_PAGESIZE);
1010 const uint64_t result = pages * page_size;
1011# define UINT64_FORMAT "%" PRIu64
1012
1013 if (_launcher_debug) {
1014 printf("pages: " UINT64_FORMAT
1015 " page_size: " UINT64_FORMAT
1016 " physical memory: " UINT64_FORMAT " (%.3fGB)\n",
1017 pages, page_size, result, result / (double) GB);
1018 }
1019 return result;
1020}
1021
1022#if defined(__sparc)
1023
1024/* Methods for solaris-sparc and linux-sparc: these are easy. */
1025
1026/* Ask the OS how many processors there are. */
1027unsigned long
1028physical_processors(void) {
1029 const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
1030
1031 if (_launcher_debug) {
1032 printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
1033 }
1034 return sys_processors;
1035}
1036
1037/* The sparc version of the "server-class" predicate. */
1038jboolean
1039unix_sparc_ServerClassMachine(void) {
1040 jboolean result = JNI_FALSE;
1041 /* How big is a server class machine? */
1042 const unsigned long server_processors = 2UL;
1043 const uint64_t server_memory = 2UL * GB;
1044 const uint64_t actual_memory = physical_memory();
1045
1046 /* Is this a server class machine? */
1047 if (actual_memory >= server_memory) {
1048 const unsigned long actual_processors = physical_processors();
1049 if (actual_processors >= server_processors) {
1050 result = JNI_TRUE;
1051 }
1052 }
1053 if (_launcher_debug) {
1054 printf("unix_" LIBARCHNAME "_ServerClassMachine: %s\n",
1055 (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE"));
1056 }
1057 return result;
1058}
1059
1060#endif /* __sparc */
1061
1062#if defined(__sun) && defined(i586)
1063
1064/*
1065 * A utility method for asking the CPU about itself.
1066 * There's a corresponding version of linux-i586
1067 * because the compilers are different.
1068 */
1069void
1070get_cpuid(uint32_t arg,
1071 uint32_t* eaxp,
1072 uint32_t* ebxp,
1073 uint32_t* ecxp,
1074 uint32_t* edxp) {
1075#ifdef _LP64
1076 asm(
1077 /* rbx is a callee-saved register */
1078 " movq %rbx, %r11 \n"
1079 /* rdx and rcx are 3rd and 4th argument registers */
1080 " movq %rdx, %r10 \n"
1081 " movq %rcx, %r9 \n"
1082 " movl %edi, %eax \n"
1083 " cpuid \n"
1084 " movl %eax, (%rsi)\n"
1085 " movl %ebx, (%r10)\n"
1086 " movl %ecx, (%r9) \n"
1087 " movl %edx, (%r8) \n"
1088 /* Restore rbx */
1089 " movq %r11, %rbx");
1090#else
1091 /* EBX is a callee-saved register */
1092 asm(" pushl %ebx");
1093 /* Need ESI for storing through arguments */
1094 asm(" pushl %esi");
1095 asm(" movl 8(%ebp), %eax \n"
1096 " cpuid \n"
1097 " movl 12(%ebp), %esi \n"
1098 " movl %eax, (%esi) \n"
1099 " movl 16(%ebp), %esi \n"
1100 " movl %ebx, (%esi) \n"
1101 " movl 20(%ebp), %esi \n"
1102 " movl %ecx, (%esi) \n"
1103 " movl 24(%ebp), %esi \n"
1104 " movl %edx, (%esi) ");
1105 /* Restore ESI and EBX */
1106 asm(" popl %esi");
1107 /* Restore EBX */
1108 asm(" popl %ebx");
1109#endif
1110}
1111
1112#endif /* __sun && i586 */
1113
1114#if defined(__linux__) && defined(i586)
1115
1116/*
1117 * A utility method for asking the CPU about itself.
1118 * There's a corresponding version of solaris-i586
1119 * because the compilers are different.
1120 */
1121void
1122get_cpuid(uint32_t arg,
1123 uint32_t* eaxp,
1124 uint32_t* ebxp,
1125 uint32_t* ecxp,
1126 uint32_t* edxp) {
1127#ifdef _LP64
1128 __asm__ volatile (/* Instructions */
1129 " movl %4, %%eax \n"
1130 " cpuid \n"
1131 " movl %%eax, (%0)\n"
1132 " movl %%ebx, (%1)\n"
1133 " movl %%ecx, (%2)\n"
1134 " movl %%edx, (%3)\n"
1135 : /* Outputs */
1136 : /* Inputs */
1137 "r" (eaxp),
1138 "r" (ebxp),
1139 "r" (ecxp),
1140 "r" (edxp),
1141 "r" (arg)
1142 : /* Clobbers */
1143 "%rax", "%rbx", "%rcx", "%rdx", "memory"
1144 );
1145#else
1146 uint32_t value_of_eax = 0;
1147 uint32_t value_of_ebx = 0;
1148 uint32_t value_of_ecx = 0;
1149 uint32_t value_of_edx = 0;
1150 __asm__ volatile (/* Instructions */
1151 /* ebx is callee-save, so push it */
1152 " pushl %%ebx \n"
1153 " movl %4, %%eax \n"
1154 " cpuid \n"
1155 " movl %%eax, %0 \n"
1156 " movl %%ebx, %1 \n"
1157 " movl %%ecx, %2 \n"
1158 " movl %%edx, %3 \n"
1159 /* restore ebx */
1160 " popl %%ebx \n"
1161
1162 : /* Outputs */
1163 "=m" (value_of_eax),
1164 "=m" (value_of_ebx),
1165 "=m" (value_of_ecx),
1166 "=m" (value_of_edx)
1167 : /* Inputs */
1168 "m" (arg)
1169 : /* Clobbers */
1170 "%eax", "%ecx", "%edx"
1171 );
1172 *eaxp = value_of_eax;
1173 *ebxp = value_of_ebx;
1174 *ecxp = value_of_ecx;
1175 *edxp = value_of_edx;
1176#endif
1177}
1178
1179#endif /* __linux__ && i586 */
1180
1181#ifdef i586
1182/*
1183 * Routines shared by solaris-i586 and linux-i586.
1184 */
1185
1186enum HyperThreadingSupport_enum {
1187 hts_supported = 1,
1188 hts_too_soon_to_tell = 0,
1189 hts_not_supported = -1,
1190 hts_not_pentium4 = -2,
1191 hts_not_intel = -3
1192};
1193typedef enum HyperThreadingSupport_enum HyperThreadingSupport;
1194
1195/* Determine if hyperthreading is supported */
1196HyperThreadingSupport
1197hyperthreading_support(void) {
1198 HyperThreadingSupport result = hts_too_soon_to_tell;
1199 /* Bits 11 through 8 is family processor id */
1200# define FAMILY_ID_SHIFT 8
1201# define FAMILY_ID_MASK 0xf
1202 /* Bits 23 through 20 is extended family processor id */
1203# define EXT_FAMILY_ID_SHIFT 20
1204# define EXT_FAMILY_ID_MASK 0xf
1205 /* Pentium 4 family processor id */
1206# define PENTIUM4_FAMILY_ID 0xf
1207 /* Bit 28 indicates Hyper-Threading Technology support */
1208# define HT_BIT_SHIFT 28
1209# define HT_BIT_MASK 1
1210 uint32_t vendor_id[3] = { 0U, 0U, 0U };
1211 uint32_t value_of_eax = 0U;
1212 uint32_t value_of_edx = 0U;
1213 uint32_t dummy = 0U;
1214
1215 /* Yes, this is supposed to be [0], [2], [1] */
1216 get_cpuid(0, &dummy, &vendor_id[0], &vendor_id[2], &vendor_id[1]);
1217 if (_launcher_debug) {
1218 printf("vendor: %c %c %c %c %c %c %c %c %c %c %c %c \n",
1219 ((vendor_id[0] >> 0) & 0xff),
1220 ((vendor_id[0] >> 8) & 0xff),
1221 ((vendor_id[0] >> 16) & 0xff),
1222 ((vendor_id[0] >> 24) & 0xff),
1223 ((vendor_id[1] >> 0) & 0xff),
1224 ((vendor_id[1] >> 8) & 0xff),
1225 ((vendor_id[1] >> 16) & 0xff),
1226 ((vendor_id[1] >> 24) & 0xff),
1227 ((vendor_id[2] >> 0) & 0xff),
1228 ((vendor_id[2] >> 8) & 0xff),
1229 ((vendor_id[2] >> 16) & 0xff),
1230 ((vendor_id[2] >> 24) & 0xff));
1231 }
1232 get_cpuid(1, &value_of_eax, &dummy, &dummy, &value_of_edx);
1233 if (_launcher_debug) {
1234 printf("value_of_eax: 0x%x value_of_edx: 0x%x\n",
1235 value_of_eax, value_of_edx);
1236 }
1237 if ((((value_of_eax >> FAMILY_ID_SHIFT) & FAMILY_ID_MASK) == PENTIUM4_FAMILY_ID) ||
1238 (((value_of_eax >> EXT_FAMILY_ID_SHIFT) & EXT_FAMILY_ID_MASK) != 0)) {
1239 if ((((vendor_id[0] >> 0) & 0xff) == 'G') &&
1240 (((vendor_id[0] >> 8) & 0xff) == 'e') &&
1241 (((vendor_id[0] >> 16) & 0xff) == 'n') &&
1242 (((vendor_id[0] >> 24) & 0xff) == 'u') &&
1243 (((vendor_id[1] >> 0) & 0xff) == 'i') &&
1244 (((vendor_id[1] >> 8) & 0xff) == 'n') &&
1245 (((vendor_id[1] >> 16) & 0xff) == 'e') &&
1246 (((vendor_id[1] >> 24) & 0xff) == 'I') &&
1247 (((vendor_id[2] >> 0) & 0xff) == 'n') &&
1248 (((vendor_id[2] >> 8) & 0xff) == 't') &&
1249 (((vendor_id[2] >> 16) & 0xff) == 'e') &&
1250 (((vendor_id[2] >> 24) & 0xff) == 'l')) {
1251 if (((value_of_edx >> HT_BIT_SHIFT) & HT_BIT_MASK) == HT_BIT_MASK) {
1252 if (_launcher_debug) {
1253 printf("Hyperthreading supported\n");
1254 }
1255 result = hts_supported;
1256 } else {
1257 if (_launcher_debug) {
1258 printf("Hyperthreading not supported\n");
1259 }
1260 result = hts_not_supported;
1261 }
1262 } else {
1263 if (_launcher_debug) {
1264 printf("Not GenuineIntel\n");
1265 }
1266 result = hts_not_intel;
1267 }
1268 } else {
1269 if (_launcher_debug) {
1270 printf("not Pentium 4 or extended\n");
1271 }
1272 result = hts_not_pentium4;
1273 }
1274 return result;
1275}
1276
1277/* Determine how many logical processors there are per CPU */
1278unsigned int
1279logical_processors_per_package(void) {
1280 /*
1281 * After CPUID with EAX==1, register EBX bits 23 through 16
1282 * indicate the number of logical processors per package
1283 */
1284# define NUM_LOGICAL_SHIFT 16
1285# define NUM_LOGICAL_MASK 0xff
1286 unsigned int result = 1U;
1287 const HyperThreadingSupport hyperthreading = hyperthreading_support();
1288
1289 if (hyperthreading == hts_supported) {
1290 uint32_t value_of_ebx = 0U;
1291 uint32_t dummy = 0U;
1292
1293 get_cpuid(1, &dummy, &value_of_ebx, &dummy, &dummy);
1294 result = (value_of_ebx >> NUM_LOGICAL_SHIFT) & NUM_LOGICAL_MASK;
1295 if (_launcher_debug) {
1296 printf("logical processors per package: %u\n", result);
1297 }
1298 }
1299 return result;
1300}
1301
1302/* Compute the number of physical processors, not logical processors */
1303unsigned long
1304physical_processors(void) {
1305 const long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
1306 unsigned long result = sys_processors;
1307
1308 if (_launcher_debug) {
1309 printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
1310 }
1311 if (sys_processors > 1) {
1312 unsigned int logical_processors = logical_processors_per_package();
1313 if (logical_processors > 1) {
1314 result = (unsigned long) sys_processors / logical_processors;
1315 }
1316 }
1317 if (_launcher_debug) {
1318 printf("physical processors: %lu\n", result);
1319 }
1320 return result;
1321}
1322
1323#endif /* i586 */
1324
1325#if defined(__sun) && defined(i586)
1326
1327/* The definition of a server-class machine for solaris-i586/amd64 */
1328jboolean
1329solaris_i586_ServerClassMachine(void) {
1330 jboolean result = JNI_FALSE;
1331 /* How big is a server class machine? */
1332 const unsigned long server_processors = 2UL;
1333 const uint64_t server_memory = 2UL * GB;
1334 /*
1335 * We seem not to get our full complement of memory.
1336 * We allow some part (1/8?) of the memory to be "missing",
1337 * based on the sizes of DIMMs, and maybe graphics cards.
1338 */
1339 const uint64_t missing_memory = 256UL * MB;
1340 const uint64_t actual_memory = physical_memory();
1341
1342 /* Is this a server class machine? */
1343 if (actual_memory >= (server_memory - missing_memory)) {
1344 const unsigned long actual_processors = physical_processors();
1345 if (actual_processors >= server_processors) {
1346 result = JNI_TRUE;
1347 }
1348 }
1349 if (_launcher_debug) {
1350 printf("solaris_" LIBARCHNAME "_ServerClassMachine: %s\n",
1351 (result == JNI_TRUE ? "true" : "false"));
1352 }
1353 return result;
1354}
1355
1356#endif /* __sun && i586 */
1357
1358#if defined(__linux__) && defined(i586)
1359
1360/* The definition of a server-class machine for linux-i586 */
1361jboolean
1362linux_i586_ServerClassMachine(void) {
1363 jboolean result = JNI_FALSE;
1364 /* How big is a server class machine? */
1365 const unsigned long server_processors = 2UL;
1366 const uint64_t server_memory = 2UL * GB;
1367 /*
1368 * We seem not to get our full complement of memory.
1369 * We allow some part (1/8?) of the memory to be "missing",
1370 * based on the sizes of DIMMs, and maybe graphics cards.
1371 */
1372 const uint64_t missing_memory = 256UL * MB;
1373 const uint64_t actual_memory = physical_memory();
1374
1375 /* Is this a server class machine? */
1376 if (actual_memory >= (server_memory - missing_memory)) {
1377 const unsigned long actual_processors = physical_processors();
1378 if (actual_processors >= server_processors) {
1379 result = JNI_TRUE;
1380 }
1381 }
1382 if (_launcher_debug) {
1383 printf("linux_" LIBARCHNAME "_ServerClassMachine: %s\n",
1384 (result == JNI_TRUE ? "true" : "false"));
1385 }
1386 return result;
1387}
1388
1389#endif /* __linux__ && i586 */
1390
1391/* Dispatch to the platform-specific definition of "server-class" */
1392jboolean
1393ServerClassMachine(void) {
1394 jboolean result = JNI_FALSE;
1395#if defined(NEVER_ACT_AS_SERVER_CLASS_MACHINE)
1396 result = JNI_FALSE;
1397#elif defined(ALWAYS_ACT_AS_SERVER_CLASS_MACHINE)
1398 result = JNI_TRUE;
1399#elif defined(__sun) && defined(__sparc)
1400 result = unix_sparc_ServerClassMachine();
1401#elif defined(__sun) && defined(i586)
1402 result = solaris_i586_ServerClassMachine();
1403#elif defined(__linux__) && defined(i586)
1404 result = linux_i586_ServerClassMachine();
1405#else
1406 if (_launcher_debug) {
1407 printf("ServerClassMachine: returns default value of %s\n",
1408 (result == JNI_TRUE ? "true" : "false"));
1409 }
1410#endif
1411 return result;
1412}
1413
1414/*
1415 * Since using the file system as a registry is a bit risky, perform
1416 * additional sanity checks on the identified directory to validate
1417 * it as a valid jre/sdk.
1418 *
1419 * Return 0 if the tests fail; otherwise return non-zero (true).
1420 *
1421 * Note that checking for anything more than the existence of an
1422 * executable object at bin/java relative to the path being checked
1423 * will break the regression tests.
1424 */
1425static int
1426CheckSanity(char *path, char *dir)
1427{
1428 char buffer[PATH_MAX];
1429
1430 if (strlen(path) + strlen(dir) + 11 > PATH_MAX)
1431 return (0); /* Silently reject "impossibly" long paths */
1432
1433 (void)strcat(strcat(strcat(strcpy(buffer, path), "/"), dir), "/bin/java");
1434 return ((access(buffer, X_OK) == 0) ? 1 : 0);
1435}
1436
1437/*
1438 * Determine if there is an acceptable JRE in the directory dirname.
1439 * Upon locating the "best" one, return a fully qualified path to
1440 * it. "Best" is defined as the most advanced JRE meeting the
1441 * constraints contained in the manifest_info. If no JRE in this
1442 * directory meets the constraints, return NULL.
1443 *
1444 * Note that we don't check for errors in reading the directory
1445 * (which would be done by checking errno). This is because it
1446 * doesn't matter if we get an error reading the directory, or
1447 * we just don't find anything interesting in the directory. We
1448 * just return NULL in either case.
1449 *
1450 * The historical names of j2sdk and j2re were changed to jdk and
1451 * jre respecively as part of the 1.5 rebranding effort. Since the
1452 * former names are legacy on Linux, they must be recognized for
1453 * all time. Fortunately, this is a minor cost.
1454 */
1455static char
1456*ProcessDir(manifest_info *info, char *dirname)
1457{
1458 DIR *dirp;
1459 struct dirent *dp;
1460 char *best = NULL;
1461 int offset;
1462 int best_offset = 0;
1463 char *ret_str = NULL;
1464 char buffer[PATH_MAX];
1465
1466 if ((dirp = opendir(dirname)) == NULL)
1467 return (NULL);
1468
1469 do {
1470 if ((dp = readdir(dirp)) != NULL) {
1471 offset = 0;
1472 if ((strncmp(dp->d_name, "jre", 3) == 0) ||
1473 (strncmp(dp->d_name, "jdk", 3) == 0))
1474 offset = 3;
1475 else if (strncmp(dp->d_name, "j2re", 4) == 0)
1476 offset = 4;
1477 else if (strncmp(dp->d_name, "j2sdk", 5) == 0)
1478 offset = 5;
1479 if (offset > 0) {
1480 if ((JLI_AcceptableRelease(dp->d_name + offset,
1481 info->jre_version)) && CheckSanity(dirname, dp->d_name))
1482 if ((best == NULL) || (JLI_ExactVersionId(
1483 dp->d_name + offset, best + best_offset) > 0)) {
1484 if (best != NULL)
1485 JLI_MemFree(best);
1486 best = JLI_StringDup(dp->d_name);
1487 best_offset = offset;
1488 }
1489 }
1490 }
1491 } while (dp != NULL);
1492 (void) closedir(dirp);
1493 if (best == NULL)
1494 return (NULL);
1495 else {
1496 ret_str = JLI_MemAlloc(strlen(dirname) + strlen(best) + 2);
1497 ret_str = strcat(strcat(strcpy(ret_str, dirname), "/"), best);
1498 JLI_MemFree(best);
1499 return (ret_str);
1500 }
1501}
1502
1503/*
1504 * This is the global entry point. It examines the host for the optimal
1505 * JRE to be used by scanning a set of directories. The set of directories
1506 * is platform dependent and can be overridden by the environment
1507 * variable JAVA_VERSION_PATH.
1508 *
1509 * This routine itself simply determines the set of appropriate
1510 * directories before passing control onto ProcessDir().
1511 */
1512char*
1513LocateJRE(manifest_info* info)
1514{
1515 char *path;
1516 char *home;
1517 char *target = NULL;
1518 char *dp;
1519 char *cp;
1520
1521 /*
1522 * Start by getting JAVA_VERSION_PATH
1523 */
1524 if (info->jre_restrict_search)
1525 path = JLI_StringDup(system_dir);
1526 else if ((path = getenv("JAVA_VERSION_PATH")) != NULL)
1527 path = JLI_StringDup(path);
1528 else
1529 if ((home = getenv("HOME")) != NULL) {
1530 path = (char *)JLI_MemAlloc(strlen(home) + strlen(system_dir) +
1531 strlen(user_dir) + 2);
1532 path = strcat(strcat(strcat(strcpy(path, home),
1533 user_dir), ":"), system_dir);
1534 } else
1535 path = JLI_StringDup(system_dir);
1536
1537 /*
1538 * Step through each directory on the path. Terminate the scan with
1539 * the first directory with an acceptable JRE.
1540 */
1541 cp = dp = path;
1542 while (dp != NULL) {
1543 cp = strchr(dp, (int)':');
1544 if (cp != NULL)
1545 *cp = (char)NULL;
1546 if ((target = ProcessDir(info, dp)) != NULL)
1547 break;
1548 dp = cp;
1549 if (dp != NULL)
1550 dp++;
1551 }
1552 JLI_MemFree(path);
1553 return (target);
1554}
1555
1556/*
1557 * Given a path to a jre to execute, this routine checks if this process
1558 * is indeed that jre. If not, it exec's that jre.
1559 *
1560 * We want to actually check the paths rather than just the version string
1561 * built into the executable, so that given version specification (and
1562 * JAVA_VERSION_PATH) will yield the exact same Java environment, regardless
1563 * of the version of the arbitrary launcher we start with.
1564 */
1565void
1566ExecJRE(char *jre, char **argv)
1567{
1568 char wanted[PATH_MAX];
1569 char *execname;
1570 char *progname;
1571
1572 /*
1573 * Resolve the real path to the directory containing the selected JRE.
1574 */
1575 if (realpath(jre, wanted) == NULL) {
1576 fprintf(stderr, "Unable to resolve %s\n", jre);
1577 exit(1);
1578 }
1579
1580 /*
1581 * Resolve the real path to the currently running launcher.
1582 */
1583 execname = SetExecname(argv);
1584 if (execname == NULL) {
1585 fprintf(stderr, "Unable to resolve current executable\n");
1586 exit(1);
1587 }
1588
1589 /*
1590 * If the path to the selected JRE directory is a match to the initial
1591 * portion of the path to the currently executing JRE, we have a winner!
1592 * If so, just return.
1593 */
1594 if (strncmp(wanted, execname, strlen(wanted)) == 0)
1595 return; /* I am the droid you were looking for */
1596
1597 /*
1598 * If this isn't the selected version, exec the selected version.
1599 */
1600#ifdef JAVA_ARGS /* javac, jar and friends. */
1601 progname = "java";
1602#else /* java, oldjava, javaw and friends */
1603#ifdef PROGNAME
1604 progname = PROGNAME;
1605#else
1606 progname = *argv;
1607 if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) {
1608 progname = s + 1;
1609 }
1610#endif /* PROGNAME */
1611#endif /* JAVA_ARGS */
1612
1613 /*
1614 * This should never happen (because of the selection code in SelectJRE),
1615 * but check for "impossibly" long path names just because buffer overruns
1616 * can be so deadly.
1617 */
1618 if (strlen(wanted) + strlen(progname) + 6 > PATH_MAX) {
1619 fprintf(stderr, "Path length exceeds maximum length (PATH_MAX)\n");
1620 exit(1);
1621 }
1622
1623 /*
1624 * Construct the path and exec it.
1625 */
1626 (void)strcat(strcat(wanted, "/bin/"), progname);
1627 argv[0] = progname;
1628 if (_launcher_debug) {
1629 int i;
1630 printf("ReExec Command: %s (%s)\n", wanted, argv[0]);
1631 printf("ReExec Args:");
1632 for (i = 1; argv[i] != NULL; i++)
1633 printf(" %s", argv[i]);
1634 printf("\n");
1635 }
1636 (void)fflush(stdout);
1637 (void)fflush(stderr);
1638 execv(wanted, argv);
1639 perror("execv()");
1640 fprintf(stderr, "Exec of %s failed\n", wanted);
1641 exit(1);
1642}
1643
1644/*
1645 * "Borrowed" from Solaris 10 where the unsetenv() function is being added
1646 * to libc thanks to SUSv3 (Standard Unix Specification, version 3). As
1647 * such, in the fullness of time this will appear in libc on all relevant
1648 * Solaris/Linux platforms and maybe even the Windows platform. At that
1649 * time, this stub can be removed.
1650 *
1651 * This implementation removes the environment locking for multithreaded
1652 * applications. (We don't have access to these mutexes within libc and
1653 * the launcher isn't multithreaded.) Note that what remains is platform
1654 * independent, because it only relies on attributes that a POSIX environment
1655 * defines.
1656 *
1657 * Returns 0 on success, -1 on failure.
1658 *
1659 * Also removed was the setting of errno. The only value of errno set
1660 * was EINVAL ("Invalid Argument").
1661 */
1662
1663/*
1664 * s1(environ) is name=value
1665 * s2(name) is name(not the form of name=value).
1666 * if names match, return value of 1, else return 0
1667 */
1668static int
1669match_noeq(const char *s1, const char *s2)
1670{
1671 while (*s1 == *s2++) {
1672 if (*s1++ == '=')
1673 return (1);
1674 }
1675 if (*s1 == '=' && s2[-1] == '\0')
1676 return (1);
1677 return (0);
1678}
1679
1680/*
1681 * added for SUSv3 standard
1682 *
1683 * Delete entry from environ.
1684 * Do not free() memory! Other threads may be using it.
1685 * Keep it around forever.
1686 */
1687static int
1688borrowed_unsetenv(const char *name)
1689{
1690 long idx; /* index into environ */
1691
1692 if (name == NULL || *name == '\0' ||
1693 strchr(name, '=') != NULL) {
1694 return (-1);
1695 }
1696
1697 for (idx = 0; environ[idx] != NULL; idx++) {
1698 if (match_noeq(environ[idx], name))
1699 break;
1700 }
1701 if (environ[idx] == NULL) {
1702 /* name not found but still a success */
1703 return (0);
1704 }
1705 /* squeeze up one entry */
1706 do {
1707 environ[idx] = environ[idx+1];
1708 } while (environ[++idx] != NULL);
1709
1710 return (0);
1711}
1712/* --- End of "borrowed" code --- */
1713
1714/*
1715 * Wrapper for unsetenv() function.
1716 */
1717int
1718UnsetEnv(char *name)
1719{
1720 return(borrowed_unsetenv(name));
1721}
1722
1723/* --- Splash Screen shared library support --- */
1724
1725static const char* SPLASHSCREEN_SO = "libsplashscreen.so";
1726
1727static void* hSplashLib = NULL;
1728
1729void* SplashProcAddress(const char* name) {
1730 if (!hSplashLib) {
1731 hSplashLib = dlopen(SPLASHSCREEN_SO, RTLD_LAZY | RTLD_GLOBAL);
1732 }
1733 if (hSplashLib) {
1734 void* sym = dlsym(hSplashLib, name);
1735 return sym;
1736 } else {
1737 return NULL;
1738 }
1739}
1740
1741void SplashFreeLibrary() {
1742 if (hSplashLib) {
1743 dlclose(hSplashLib);
1744 hSplashLib = NULL;
1745 }
1746}
1747
1748const char *
1749jlong_format_specifier() {
1750 return "%lld";
1751}
1752
1753/*
1754 * Block current thread and continue execution in a new thread
1755 */
1756int
1757ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void * args, int ret) {
1758 int rslt;
1759#ifdef __linux__
1760 pthread_t tid;
1761 pthread_attr_t attr;
1762 pthread_attr_init(&attr);
1763 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1764
1765 if (stack_size > 0) {
1766 pthread_attr_setstacksize(&attr, stack_size);
1767 }
1768
1769 if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) {
1770 void * tmp;
1771 pthread_join(tid, &tmp);
1772 rslt = (int)tmp;
1773 } else {
1774 /*
1775 * Continue execution in current thread if for some reason (e.g. out of
1776 * memory/LWP) a new thread can't be created. This will likely fail
1777 * later in continuation as JNI_CreateJavaVM needs to create quite a
1778 * few new threads, anyway, just give it a try..
1779 */
1780 rslt = continuation(args);
1781 }
1782
1783 pthread_attr_destroy(&attr);
1784#else
1785 thread_t tid;
1786 long flags = 0;
1787 if (thr_create(NULL, stack_size, (void *(*)(void *))continuation, args, flags, &tid) == 0) {
1788 void * tmp;
1789 thr_join(tid, NULL, &tmp);
1790 rslt = (int)tmp;
1791 } else {
1792 /* See above. Continue in current thread if thr_create() failed */
1793 rslt = continuation(args);
1794 }
1795#endif
1796 /* If the caller has deemed there is an error we
1797 * simply return that, otherwise we return the value of
1798 * the callee
1799 */
1800 return (ret != 0) ? ret : rslt;
1801}
1802
1803/* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */
1804#define MAX_PID_STR_SZ 20
1805
1806void SetJavaLauncherPlatformProps() {
1807 /* Linux only */
1808#ifdef __linux__
1809 const char *substr = "-Dsun.java.launcher.pid=";
1810 char *pid_prop_str = (char *)JLI_MemAlloc(strlen(substr) + MAX_PID_STR_SZ + 1);
1811 sprintf(pid_prop_str, "%s%d", substr, getpid());
1812 AddOption(pid_prop_str, NULL);
1813#endif
1814}
Note: See TracBrowser for help on using the repository browser.