34 #include <stdlib.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <sys/types.h>
38 #include "manifest_info.h"
39
40
41 #define JVM_DLL "libjvm.so"
42 #define JAVA_DLL "libjava.so"
43 #ifdef AIX
44 #define LD_LIBRARY_PATH "LIBPATH"
45 #else
46 #define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
47 #endif
48
49 /* help jettison the LD_LIBRARY_PATH settings in the future */
50 #ifndef SETENV_REQUIRED
51 #define SETENV_REQUIRED
52 #endif
53
54 #ifdef __solaris__
55 # include <sys/systeminfo.h>
56 # include <sys/elf.h>
57 # include <stdio.h>
58 #endif
59
60 /*
61 * Flowchart of launcher execs and options processing on unix
62 *
63 * The selection of the proper vm shared library to open depends on
64 * several classes of command line options, including vm "flavor"
65 * options (-client, -server).
66 * The vm selection options are not passed to the running
67 * virtual machine; they must be screened out by the launcher.
68 *
69 * The version specification (if any) is processed first by the
70 * platform independent routine SelectVersion. This may result in
71 * the exec of the specified launcher version.
72 *
73 * Previously the launcher modified the LD_LIBRARY_PATH appropriately for the
74 * desired data model path, regardless if data models matched or not. The
75 * launcher subsequently exec'ed the desired executable, in order to make the
76 * LD_LIBRARY_PATH path available, for the runtime linker.
77 *
78 * Now, in most cases,the launcher will dlopen the target libjvm.so. All
79 * required libraries are loaded by the runtime linker, using the
225 JLI_MemFree(envpath);
226 return JNI_FALSE;
227 }
228
229 /*
230 * Test whether the environment variable needs to be set, see flowchart.
231 */
232 static jboolean
233 RequiresSetenv(const char *jvmpath) {
234 char jpath[PATH_MAX + 1];
235 char *llp;
236 char *dmllp = NULL;
237 char *p; /* a utility pointer */
238
239 #ifdef AIX
240 /* We always have to set the LIBPATH on AIX because ld doesn't support $ORIGIN. */
241 return JNI_TRUE;
242 #endif
243
244 llp = getenv("LD_LIBRARY_PATH");
245 #ifdef __solaris__
246 dmllp = getenv("LD_LIBRARY_PATH_64");
247 #endif /* __solaris__ */
248 /* no environment variable is a good environment variable */
249 if (llp == NULL && dmllp == NULL) {
250 return JNI_FALSE;
251 }
252 #ifdef __linux
253 /*
254 * On linux, if a binary is running as sgid or suid, glibc sets
255 * LD_LIBRARY_PATH to the empty string for security purposes. (In contrast,
256 * on Solaris the LD_LIBRARY_PATH variable for a privileged binary does not
257 * lose its settings; but the dynamic linker does apply more scrutiny to the
258 * path.) The launcher uses the value of LD_LIBRARY_PATH to prevent an exec
259 * loop, here and further downstream. Therefore, if we are running sgid or
260 * suid, this function's setting of LD_LIBRARY_PATH will be ineffective and
261 * we should case a return from the calling function. Getting the right
262 * libraries will be handled by the RPATH. In reality, this check is
263 * redundant, as the previous check for a non-null LD_LIBRARY_PATH will
264 * return back to the calling function forthwith, it is left here to safe
265 * guard against any changes, in the glibc's existing security policy.
266 */
267 if ((getgid() != getegid()) || (getuid() != geteuid())) {
287 }
288 if (dmllp != NULL && ContainsLibJVM(dmllp)) {
289 return JNI_TRUE;
290 }
291 return JNI_FALSE;
292 }
293 #endif /* SETENV_REQUIRED */
294
295 void
296 CreateExecutionEnvironment(int *pargc, char ***pargv,
297 char jrepath[], jint so_jrepath,
298 char jvmpath[], jint so_jvmpath,
299 char jvmcfg[], jint so_jvmcfg) {
300
301 char * jvmtype = NULL;
302 int argc = *pargc;
303 char **argv = *pargv;
304
305 #ifdef SETENV_REQUIRED
306 jboolean mustsetenv = JNI_FALSE;
307 #ifdef __solaris__
308 char *llp64 = NULL; /* existing LD_LIBRARY_PATH_64 setting */
309 #endif // __solaris__
310 char *runpath = NULL; /* existing effective LD_LIBRARY_PATH setting */
311 char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */
312 char* newpath = NULL; /* path on new LD_LIBRARY_PATH */
313 char* lastslash = NULL;
314 char** newenvp = NULL; /* current environment */
315 size_t new_runpath_size;
316 #endif /* SETENV_REQUIRED */
317
318 /* Compute/set the name of the executable */
319 SetExecname(*pargv);
320
321 /* Check to see if the jvmpath exists */
322 /* Find out where the JRE is that we will be using. */
323 if (!GetJREPath(jrepath, so_jrepath, JNI_FALSE)) {
324 JLI_ReportErrorMessage(JRE_ERROR1);
325 exit(2);
326 }
327 JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%sjvm.cfg",
328 jrepath, FILESEP, FILESEP);
329 /* Find the specified JVM type */
354 if (mustsetenv == JNI_FALSE) {
355 return;
356 }
357 #else
358 return;
359 #endif /* SETENV_REQUIRED */
360
361 #ifdef SETENV_REQUIRED
362 if (mustsetenv) {
363 /*
364 * We will set the LD_LIBRARY_PATH as follows:
365 *
366 * o $JVMPATH (directory portion only)
367 * o $JRE/lib
368 * o $JRE/../lib
369 *
370 * followed by the user's previous effective LD_LIBRARY_PATH, if
371 * any.
372 */
373
374 #ifdef __solaris__
375 llp64 = getenv("LD_LIBRARY_PATH_64");
376 runpath = (llp64 == NULL) ? getenv(LD_LIBRARY_PATH) : llp64;
377 #else
378 runpath = getenv(LD_LIBRARY_PATH);
379 #endif /* __solaris__ */
380
381 /* runpath contains current effective LD_LIBRARY_PATH setting */
382 { /* New scope to declare local variable */
383 char *new_jvmpath = JLI_StringDup(jvmpath);
384 new_runpath_size = ((runpath != NULL) ? JLI_StrLen(runpath) : 0) +
385 2 * JLI_StrLen(jrepath) +
386 JLI_StrLen(new_jvmpath) + 52;
387 new_runpath = JLI_MemAlloc(new_runpath_size);
388 newpath = new_runpath + JLI_StrLen(LD_LIBRARY_PATH "=");
389
390
391 /*
392 * Create desired LD_LIBRARY_PATH value for target data model.
393 */
394 {
395 /* remove the name of the .so from the JVM path */
396 lastslash = JLI_StrRChr(new_jvmpath, '/');
397 if (lastslash)
398 *lastslash = '\0';
399
432 if (runpath != 0) {
433 /* ensure storage for runpath + colon + NULL */
434 if ((JLI_StrLen(runpath) + 1 + 1) > new_runpath_size) {
435 JLI_ReportErrorMessageSys(JRE_ERROR11);
436 exit(1);
437 }
438 JLI_StrCat(new_runpath, ":");
439 JLI_StrCat(new_runpath, runpath);
440 }
441
442 if (putenv(new_runpath) != 0) {
443 /* problem allocating memory; LD_LIBRARY_PATH not set properly */
444 exit(1);
445 }
446
447 /*
448 * Unix systems document that they look at LD_LIBRARY_PATH only
449 * once at startup, so we have to re-exec the current executable
450 * to get the changed environment variable to have an effect.
451 */
452 #ifdef __solaris__
453 /*
454 * new LD_LIBRARY_PATH took over for LD_LIBRARY_PATH_64
455 */
456 if (llp64 != NULL) {
457 UnsetEnv("LD_LIBRARY_PATH_64");
458 }
459 #endif // __solaris__
460
461 newenvp = environ;
462 }
463 #endif /* SETENV_REQUIRED */
464 {
465 char *newexec = execname;
466 JLI_TraceLauncher("TRACER_MARKER:About to EXEC\n");
467 (void) fflush(stdout);
468 (void) fflush(stderr);
469 #ifdef SETENV_REQUIRED
470 if (mustsetenv) {
471 execve(newexec, argv, newenvp);
472 } else {
473 execv(newexec, argv);
474 }
475 #else /* !SETENV_REQUIRED */
476 execv(newexec, argv);
477 #endif /* SETENV_REQUIRED */
478 JLI_ReportErrorMessageSys(JRE_ERROR4, newexec);
479 }
539 if (stat(libjava, &s) == 0) {
540 JLI_TraceLauncher("JRE path is %s\n", path);
541 return JNI_TRUE;
542 }
543 }
544
545 if (!speculative)
546 JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
547 return JNI_FALSE;
548 }
549
550 jboolean
551 LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
552 {
553 void *libjvm;
554
555 JLI_TraceLauncher("JVM path is %s\n", jvmpath);
556
557 libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
558 if (libjvm == NULL) {
559 #if defined(__solaris__) && defined(__sparc) && !defined(_LP64) /* i.e. 32-bit sparc */
560 FILE * fp;
561 Elf32_Ehdr elf_head;
562 int count;
563 int location;
564
565 fp = fopen(jvmpath, "r");
566 if (fp == NULL) {
567 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
568 return JNI_FALSE;
569 }
570
571 /* read in elf header */
572 count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp);
573 fclose(fp);
574 if (count < 1) {
575 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
576 return JNI_FALSE;
577 }
578
579 /*
580 * Check for running a server vm (compiled with -xarch=v8plus)
581 * on a stock v8 processor. In this case, the machine type in
582 * the elf header would not be included the architecture list
583 * provided by the isalist command, which is turn is gotten from
584 * sysinfo. This case cannot occur on 64-bit hardware and thus
585 * does not have to be checked for in binaries with an LP64 data
586 * model.
587 */
588 if (elf_head.e_machine == EM_SPARC32PLUS) {
589 char buf[257]; /* recommended buffer size from sysinfo man
590 page */
591 long length;
592 char* location;
593
594 length = sysinfo(SI_ISALIST, buf, 257);
595 if (length > 0) {
596 location = JLI_StrStr(buf, "sparcv8plus ");
597 if (location == NULL) {
598 JLI_ReportErrorMessage(JVM_ERROR3);
599 return JNI_FALSE;
600 }
601 }
602 }
603 #endif
604 JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
605 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
606 return JNI_FALSE;
607 }
608
609 ifn->CreateJavaVM = (CreateJavaVM_t)
610 dlsym(libjvm, "JNI_CreateJavaVM");
611 if (ifn->CreateJavaVM == NULL) {
612 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
613 return JNI_FALSE;
614 }
615
616 ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
617 dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");
618 if (ifn->GetDefaultJavaVMInitArgs == NULL) {
619 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
620 return JNI_FALSE;
621 }
622
623 ifn->GetCreatedJavaVMs = (GetCreatedJavaVMs_t)
630 return JNI_TRUE;
631 }
632
633 /*
634 * Compute the name of the executable
635 *
636 * In order to re-exec securely we need the absolute path of the
637 * executable. On Solaris getexecname(3c) may not return an absolute
638 * path so we use dladdr to get the filename of the executable and
639 * then use realpath to derive an absolute path. From Solaris 9
640 * onwards the filename returned in DL_info structure from dladdr is
641 * an absolute pathname so technically realpath isn't required.
642 * On Linux we read the executable name from /proc/self/exe.
643 * As a fallback, and for platforms other than Solaris and Linux,
644 * we use FindExecName to compute the executable name.
645 */
646 const char*
647 SetExecname(char **argv)
648 {
649 char* exec_path = NULL;
650 #if defined(__solaris__)
651 {
652 Dl_info dlinfo;
653 int (*fptr)();
654
655 fptr = (int (*)())dlsym(RTLD_DEFAULT, "main");
656 if (fptr == NULL) {
657 JLI_ReportErrorMessage(DLL_ERROR3, dlerror());
658 return JNI_FALSE;
659 }
660
661 if (dladdr((void*)fptr, &dlinfo)) {
662 char *resolved = (char*)JLI_MemAlloc(PATH_MAX+1);
663 if (resolved != NULL) {
664 exec_path = realpath(dlinfo.dli_fname, resolved);
665 if (exec_path == NULL) {
666 JLI_MemFree(resolved);
667 }
668 }
669 }
670 }
671 #elif defined(__linux__)
672 {
673 const char* self = "/proc/self/exe";
674 char buf[PATH_MAX+1];
675 int len = readlink(self, buf, PATH_MAX);
676 if (len >= 0) {
677 buf[len] = '\0'; /* readlink(2) doesn't NUL terminate */
678 exec_path = JLI_StringDup(buf);
679 }
680 }
681 #else /* !__solaris__ && !__linux__ */
682 {
683 /* Not implemented */
684 }
685 #endif
686
687 if (exec_path == NULL) {
688 exec_path = FindExecName(argv[0]);
689 }
690 execname = exec_path;
691 return exec_path;
692 }
693
694 /* --- Splash Screen shared library support --- */
695 static const char* SPLASHSCREEN_SO = JNI_LIB_NAME("splashscreen");
696 static void* hSplashLib = NULL;
697
698 void* SplashProcAddress(const char* name) {
699 if (!hSplashLib) {
700 int ret;
701 char jrePath[MAXPATHLEN];
723 void* sym = dlsym(hSplashLib, name);
724 return sym;
725 } else {
726 return NULL;
727 }
728 }
729
730 /*
731 * Signature adapter for pthread_create() or thr_create().
732 */
733 static void* ThreadJavaMain(void* args) {
734 return (void*)(intptr_t)JavaMain(args);
735 }
736
737 /*
738 * Block current thread and continue execution in a new thread.
739 */
740 int
741 CallJavaMainInNewThread(jlong stack_size, void* args) {
742 int rslt;
743 #ifndef __solaris__
744 pthread_t tid;
745 pthread_attr_t attr;
746 pthread_attr_init(&attr);
747 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
748
749 if (stack_size > 0) {
750 pthread_attr_setstacksize(&attr, stack_size);
751 }
752 pthread_attr_setguardsize(&attr, 0); // no pthread guard page on java threads
753
754 if (pthread_create(&tid, &attr, ThreadJavaMain, args) == 0) {
755 void* tmp;
756 pthread_join(tid, &tmp);
757 rslt = (int)(intptr_t)tmp;
758 } else {
759 /*
760 * Continue execution in current thread if for some reason (e.g. out of
761 * memory/LWP) a new thread can't be created. This will likely fail
762 * later in JavaMain as JNI_CreateJavaVM needs to create quite a
763 * few new threads, anyway, just give it a try..
764 */
765 rslt = JavaMain(args);
766 }
767
768 pthread_attr_destroy(&attr);
769 #else /* __solaris__ */
770 thread_t tid;
771 long flags = 0;
772 if (thr_create(NULL, stack_size, ThreadJavaMain, args, flags, &tid) == 0) {
773 void* tmp;
774 thr_join(tid, NULL, &tmp);
775 rslt = (int)(intptr_t)tmp;
776 } else {
777 /* See above. Continue in current thread if thr_create() failed */
778 rslt = JavaMain(args);
779 }
780 #endif /* !__solaris__ */
781 return rslt;
782 }
783
784 /* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */
785 #define MAX_PID_STR_SZ 20
786
787 int
788 JVMInit(InvocationFunctions* ifn, jlong threadStackSize,
789 int argc, char **argv,
790 int mode, char *what, int ret)
791 {
792 ShowSplashScreen();
793 return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret);
794 }
795
796 void
797 PostJVMInit(JNIEnv *env, jclass mainClass, JavaVM *vm)
798 {
799 // stubbed out for windows and *nixes.
800 }
801
802 void
803 RegisterThread()
804 {
805 // stubbed out for windows and *nixes.
806 }
807
808 /*
809 * on unix, we return a false to indicate this option is not applicable
810 */
811 jboolean
812 ProcessPlatformOption(const char *arg)
813 {
814 return JNI_FALSE;
815 }
816
817 #ifndef __solaris__
818
819 /*
820 * Provide a CounterGet() implementation based on gettimeofday() which
821 * is universally available, even though it may not be 'high resolution'
822 * compared to platforms that provide gethrtime() (like Solaris). It is
823 * also subject to time-of-day changes, but alternatives may not be
824 * known to be available at either build time or run time.
825 */
826 uint64_t CounterGet() {
827 uint64_t result = 0;
828 struct timeval tv;
829 if (gettimeofday(&tv, NULL) != -1) {
830 result = 1000000LL * (uint64_t)tv.tv_sec;
831 result += (uint64_t)tv.tv_usec;
832 }
833 return result;
834 }
835
836 #endif // !__solaris__
|
34 #include <stdlib.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <sys/types.h>
38 #include "manifest_info.h"
39
40
41 #define JVM_DLL "libjvm.so"
42 #define JAVA_DLL "libjava.so"
43 #ifdef AIX
44 #define LD_LIBRARY_PATH "LIBPATH"
45 #else
46 #define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
47 #endif
48
49 /* help jettison the LD_LIBRARY_PATH settings in the future */
50 #ifndef SETENV_REQUIRED
51 #define SETENV_REQUIRED
52 #endif
53
54 /*
55 * Flowchart of launcher execs and options processing on unix
56 *
57 * The selection of the proper vm shared library to open depends on
58 * several classes of command line options, including vm "flavor"
59 * options (-client, -server).
60 * The vm selection options are not passed to the running
61 * virtual machine; they must be screened out by the launcher.
62 *
63 * The version specification (if any) is processed first by the
64 * platform independent routine SelectVersion. This may result in
65 * the exec of the specified launcher version.
66 *
67 * Previously the launcher modified the LD_LIBRARY_PATH appropriately for the
68 * desired data model path, regardless if data models matched or not. The
69 * launcher subsequently exec'ed the desired executable, in order to make the
70 * LD_LIBRARY_PATH path available, for the runtime linker.
71 *
72 * Now, in most cases,the launcher will dlopen the target libjvm.so. All
73 * required libraries are loaded by the runtime linker, using the
219 JLI_MemFree(envpath);
220 return JNI_FALSE;
221 }
222
223 /*
224 * Test whether the environment variable needs to be set, see flowchart.
225 */
226 static jboolean
227 RequiresSetenv(const char *jvmpath) {
228 char jpath[PATH_MAX + 1];
229 char *llp;
230 char *dmllp = NULL;
231 char *p; /* a utility pointer */
232
233 #ifdef AIX
234 /* We always have to set the LIBPATH on AIX because ld doesn't support $ORIGIN. */
235 return JNI_TRUE;
236 #endif
237
238 llp = getenv("LD_LIBRARY_PATH");
239 /* no environment variable is a good environment variable */
240 if (llp == NULL && dmllp == NULL) {
241 return JNI_FALSE;
242 }
243 #ifdef __linux
244 /*
245 * On linux, if a binary is running as sgid or suid, glibc sets
246 * LD_LIBRARY_PATH to the empty string for security purposes. (In contrast,
247 * on Solaris the LD_LIBRARY_PATH variable for a privileged binary does not
248 * lose its settings; but the dynamic linker does apply more scrutiny to the
249 * path.) The launcher uses the value of LD_LIBRARY_PATH to prevent an exec
250 * loop, here and further downstream. Therefore, if we are running sgid or
251 * suid, this function's setting of LD_LIBRARY_PATH will be ineffective and
252 * we should case a return from the calling function. Getting the right
253 * libraries will be handled by the RPATH. In reality, this check is
254 * redundant, as the previous check for a non-null LD_LIBRARY_PATH will
255 * return back to the calling function forthwith, it is left here to safe
256 * guard against any changes, in the glibc's existing security policy.
257 */
258 if ((getgid() != getegid()) || (getuid() != geteuid())) {
278 }
279 if (dmllp != NULL && ContainsLibJVM(dmllp)) {
280 return JNI_TRUE;
281 }
282 return JNI_FALSE;
283 }
284 #endif /* SETENV_REQUIRED */
285
286 void
287 CreateExecutionEnvironment(int *pargc, char ***pargv,
288 char jrepath[], jint so_jrepath,
289 char jvmpath[], jint so_jvmpath,
290 char jvmcfg[], jint so_jvmcfg) {
291
292 char * jvmtype = NULL;
293 int argc = *pargc;
294 char **argv = *pargv;
295
296 #ifdef SETENV_REQUIRED
297 jboolean mustsetenv = JNI_FALSE;
298 char *runpath = NULL; /* existing effective LD_LIBRARY_PATH setting */
299 char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */
300 char* newpath = NULL; /* path on new LD_LIBRARY_PATH */
301 char* lastslash = NULL;
302 char** newenvp = NULL; /* current environment */
303 size_t new_runpath_size;
304 #endif /* SETENV_REQUIRED */
305
306 /* Compute/set the name of the executable */
307 SetExecname(*pargv);
308
309 /* Check to see if the jvmpath exists */
310 /* Find out where the JRE is that we will be using. */
311 if (!GetJREPath(jrepath, so_jrepath, JNI_FALSE)) {
312 JLI_ReportErrorMessage(JRE_ERROR1);
313 exit(2);
314 }
315 JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%sjvm.cfg",
316 jrepath, FILESEP, FILESEP);
317 /* Find the specified JVM type */
342 if (mustsetenv == JNI_FALSE) {
343 return;
344 }
345 #else
346 return;
347 #endif /* SETENV_REQUIRED */
348
349 #ifdef SETENV_REQUIRED
350 if (mustsetenv) {
351 /*
352 * We will set the LD_LIBRARY_PATH as follows:
353 *
354 * o $JVMPATH (directory portion only)
355 * o $JRE/lib
356 * o $JRE/../lib
357 *
358 * followed by the user's previous effective LD_LIBRARY_PATH, if
359 * any.
360 */
361
362 runpath = getenv(LD_LIBRARY_PATH);
363
364 /* runpath contains current effective LD_LIBRARY_PATH setting */
365 { /* New scope to declare local variable */
366 char *new_jvmpath = JLI_StringDup(jvmpath);
367 new_runpath_size = ((runpath != NULL) ? JLI_StrLen(runpath) : 0) +
368 2 * JLI_StrLen(jrepath) +
369 JLI_StrLen(new_jvmpath) + 52;
370 new_runpath = JLI_MemAlloc(new_runpath_size);
371 newpath = new_runpath + JLI_StrLen(LD_LIBRARY_PATH "=");
372
373
374 /*
375 * Create desired LD_LIBRARY_PATH value for target data model.
376 */
377 {
378 /* remove the name of the .so from the JVM path */
379 lastslash = JLI_StrRChr(new_jvmpath, '/');
380 if (lastslash)
381 *lastslash = '\0';
382
415 if (runpath != 0) {
416 /* ensure storage for runpath + colon + NULL */
417 if ((JLI_StrLen(runpath) + 1 + 1) > new_runpath_size) {
418 JLI_ReportErrorMessageSys(JRE_ERROR11);
419 exit(1);
420 }
421 JLI_StrCat(new_runpath, ":");
422 JLI_StrCat(new_runpath, runpath);
423 }
424
425 if (putenv(new_runpath) != 0) {
426 /* problem allocating memory; LD_LIBRARY_PATH not set properly */
427 exit(1);
428 }
429
430 /*
431 * Unix systems document that they look at LD_LIBRARY_PATH only
432 * once at startup, so we have to re-exec the current executable
433 * to get the changed environment variable to have an effect.
434 */
435
436 newenvp = environ;
437 }
438 #endif /* SETENV_REQUIRED */
439 {
440 char *newexec = execname;
441 JLI_TraceLauncher("TRACER_MARKER:About to EXEC\n");
442 (void) fflush(stdout);
443 (void) fflush(stderr);
444 #ifdef SETENV_REQUIRED
445 if (mustsetenv) {
446 execve(newexec, argv, newenvp);
447 } else {
448 execv(newexec, argv);
449 }
450 #else /* !SETENV_REQUIRED */
451 execv(newexec, argv);
452 #endif /* SETENV_REQUIRED */
453 JLI_ReportErrorMessageSys(JRE_ERROR4, newexec);
454 }
514 if (stat(libjava, &s) == 0) {
515 JLI_TraceLauncher("JRE path is %s\n", path);
516 return JNI_TRUE;
517 }
518 }
519
520 if (!speculative)
521 JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
522 return JNI_FALSE;
523 }
524
525 jboolean
526 LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
527 {
528 void *libjvm;
529
530 JLI_TraceLauncher("JVM path is %s\n", jvmpath);
531
532 libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
533 if (libjvm == NULL) {
534 JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
535 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
536 return JNI_FALSE;
537 }
538
539 ifn->CreateJavaVM = (CreateJavaVM_t)
540 dlsym(libjvm, "JNI_CreateJavaVM");
541 if (ifn->CreateJavaVM == NULL) {
542 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
543 return JNI_FALSE;
544 }
545
546 ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
547 dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");
548 if (ifn->GetDefaultJavaVMInitArgs == NULL) {
549 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
550 return JNI_FALSE;
551 }
552
553 ifn->GetCreatedJavaVMs = (GetCreatedJavaVMs_t)
560 return JNI_TRUE;
561 }
562
563 /*
564 * Compute the name of the executable
565 *
566 * In order to re-exec securely we need the absolute path of the
567 * executable. On Solaris getexecname(3c) may not return an absolute
568 * path so we use dladdr to get the filename of the executable and
569 * then use realpath to derive an absolute path. From Solaris 9
570 * onwards the filename returned in DL_info structure from dladdr is
571 * an absolute pathname so technically realpath isn't required.
572 * On Linux we read the executable name from /proc/self/exe.
573 * As a fallback, and for platforms other than Solaris and Linux,
574 * we use FindExecName to compute the executable name.
575 */
576 const char*
577 SetExecname(char **argv)
578 {
579 char* exec_path = NULL;
580 #if defined(__linux__)
581 {
582 const char* self = "/proc/self/exe";
583 char buf[PATH_MAX+1];
584 int len = readlink(self, buf, PATH_MAX);
585 if (len >= 0) {
586 buf[len] = '\0'; /* readlink(2) doesn't NUL terminate */
587 exec_path = JLI_StringDup(buf);
588 }
589 }
590 #else /* !__linux__ */
591 {
592 /* Not implemented */
593 }
594 #endif
595
596 if (exec_path == NULL) {
597 exec_path = FindExecName(argv[0]);
598 }
599 execname = exec_path;
600 return exec_path;
601 }
602
603 /* --- Splash Screen shared library support --- */
604 static const char* SPLASHSCREEN_SO = JNI_LIB_NAME("splashscreen");
605 static void* hSplashLib = NULL;
606
607 void* SplashProcAddress(const char* name) {
608 if (!hSplashLib) {
609 int ret;
610 char jrePath[MAXPATHLEN];
632 void* sym = dlsym(hSplashLib, name);
633 return sym;
634 } else {
635 return NULL;
636 }
637 }
638
639 /*
640 * Signature adapter for pthread_create() or thr_create().
641 */
642 static void* ThreadJavaMain(void* args) {
643 return (void*)(intptr_t)JavaMain(args);
644 }
645
646 /*
647 * Block current thread and continue execution in a new thread.
648 */
649 int
650 CallJavaMainInNewThread(jlong stack_size, void* args) {
651 int rslt;
652 pthread_t tid;
653 pthread_attr_t attr;
654 pthread_attr_init(&attr);
655 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
656
657 if (stack_size > 0) {
658 pthread_attr_setstacksize(&attr, stack_size);
659 }
660 pthread_attr_setguardsize(&attr, 0); // no pthread guard page on java threads
661
662 if (pthread_create(&tid, &attr, ThreadJavaMain, args) == 0) {
663 void* tmp;
664 pthread_join(tid, &tmp);
665 rslt = (int)(intptr_t)tmp;
666 } else {
667 /*
668 * Continue execution in current thread if for some reason (e.g. out of
669 * memory/LWP) a new thread can't be created. This will likely fail
670 * later in JavaMain as JNI_CreateJavaVM needs to create quite a
671 * few new threads, anyway, just give it a try..
672 */
673 rslt = JavaMain(args);
674 }
675
676 pthread_attr_destroy(&attr);
677 return rslt;
678 }
679
680 /* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */
681 #define MAX_PID_STR_SZ 20
682
683 int
684 JVMInit(InvocationFunctions* ifn, jlong threadStackSize,
685 int argc, char **argv,
686 int mode, char *what, int ret)
687 {
688 ShowSplashScreen();
689 return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret);
690 }
691
692 void
693 PostJVMInit(JNIEnv *env, jclass mainClass, JavaVM *vm)
694 {
695 // stubbed out for windows and *nixes.
696 }
697
698 void
699 RegisterThread()
700 {
701 // stubbed out for windows and *nixes.
702 }
703
704 /*
705 * on unix, we return a false to indicate this option is not applicable
706 */
707 jboolean
708 ProcessPlatformOption(const char *arg)
709 {
710 return JNI_FALSE;
711 }
712
713 /*
714 * Provide a CounterGet() implementation based on gettimeofday() which
715 * is universally available, even though it may not be 'high resolution'
716 * compared to platforms that provide gethrtime() (like Solaris). It is
717 * also subject to time-of-day changes, but alternatives may not be
718 * known to be available at either build time or run time.
719 */
720 uint64_t CounterGet() {
721 uint64_t result = 0;
722 struct timeval tv;
723 if (gettimeofday(&tv, NULL) != -1) {
724 result = 1000000LL * (uint64_t)tv.tv_sec;
725 result += (uint64_t)tv.tv_usec;
726 }
727 return result;
728 }
|