/* * If app is "/foo/bin/javac", or "/foo/bin/sparcv9/javac" then put * "/foo" into buf. */ jboolean GetApplicationHome(char *buf, jint bufsize) { const char *execname = GetExecName(); if (execname != NULL) { JLI_Snprintf(buf, bufsize, "%s", execname); buf[bufsize-1] = '\0'; } else { return JNI_FALSE; } if (JLI_StrRChr(buf, '/') == 0) { buf[0] = '\0'; return JNI_FALSE; } *(JLI_StrRChr(buf, '/')) = '\0'; /* executable file */ if (JLI_StrLen(buf) < 4 || JLI_StrRChr(buf, '/') == 0) { buf[0] = '\0'; return JNI_FALSE; } if (JLI_StrCmp("/bin", buf + JLI_StrLen(buf) - 4) != 0) *(JLI_StrRChr(buf, '/')) = '\0'; /* sparcv9 or amd64 */ if (JLI_StrLen(buf) < 4 || JLI_StrCmp("/bin", buf + JLI_StrLen(buf) - 4) != 0) { buf[0] = '\0'; return JNI_FALSE; } *(JLI_StrRChr(buf, '/')) = '\0'; /* bin */ return JNI_TRUE; }
/* * 根据当前java程序的启动命令解析出当前jre的安装路径,两种模式: * 1./{**}/bin/javac(java) -------> /{**}/ * 2./{**}/bin/{arch(sparcv9 or amd64)}/javac(java) -------> /{**}/ */ jboolean GetApplicationHome(char *buf, jint bufsize) { const char *execname = GetExecName(); if (execname != NULL) { JLI_Snprintf(buf, bufsize, "%s", execname); buf[bufsize-1] = '\0'; } else { return JNI_FALSE; } if (JLI_StrRChr(buf, '/') == 0) { //直接在系统根目录下,则无法找到jre安装路径 buf[0] = '\0'; return JNI_FALSE; } //去掉末尾的javac/java *(JLI_StrRChr(buf, '/')) = '\0'; /* executable file */ //非'/{**}/bin'或'/{**}/bin/{arch(sparcv9 or amd64)}'形式,则无法找到jre安装路径 if (JLI_StrLen(buf) < 4 || JLI_StrRChr(buf, '/') == 0) { buf[0] = '\0'; return JNI_FALSE; } if (JLI_StrCmp("/bin", buf + JLI_StrLen(buf) - 4) != 0) *(JLI_StrRChr(buf, '/')) = '\0'; /* sparcv9 or amd64 */ if (JLI_StrLen(buf) < 4 || JLI_StrCmp("/bin", buf + JLI_StrLen(buf) - 4) != 0) { buf[0] = '\0'; return JNI_FALSE; } *(JLI_StrRChr(buf, '/')) = '\0'; /* bin */ return JNI_TRUE; }
/* * 使用指定的jvm版本来运行java程序 * * ****************************************************************************** * 函数原型: char *realpath(const char *path, char *resolved_path); * 函数说明: 用来将参数path所指的相对路径转换成绝对路径后存于参数resolved_path所指的字符串数组或指针中 * 函数返回: 成功则返回指向resolved_path的指针,失败返回NULL,错误代码存于errno * * ****************************************************************************** * 函数原型: int execve(const char * filename,char * const argv[],char * const envp[]); * 函数说明: execve用来执行参数filename字符串所代表的文件路径,第二个参数是利用数组指针来传递给执行文件,并且需要以 * 空指针(NULL)结束,最后一个参数则为传递给执行文件的新环境变量数组.exec函数一共有六个,其中execve为内核 * 级系统调用,其他(execl,execle,execlp,execv,execvp)都是调用execve的库函数 * 函数返回: 如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中 */ void ExecJRE(char *jre, char **argv) { char wanted[PATH_MAX]; const char* progname = GetProgramName(); const char* execname = NULL; /* * 转换成绝对路径 */ if (realpath(jre, wanted) == NULL) { JLI_ReportErrorMessage(JRE_ERROR9, jre); exit(1); } /* * 获取启动当前JVM进程的命令 */ SetExecname(argv); execname = GetExecName(); if (execname == NULL) { JLI_ReportErrorMessage(JRE_ERROR10); exit(1); } /* * If the path to the selected JRE directory is a match to the initial * portion of the path to the currently executing JRE, we have a winner! * If so, just return. */ if (JLI_StrNCmp(wanted, execname, JLI_StrLen(wanted)) == 0) return; /* I am the droid you were looking for */ /* * This should never happen (because of the selection code in SelectJRE), * but check for "impossibly" long path names just because buffer overruns * can be so deadly. */ if (JLI_StrLen(wanted) + JLI_StrLen(progname) + 6 > PATH_MAX) { JLI_ReportErrorMessage(JRE_ERROR11); exit(1); } /* * Construct the path and exec it. */ (void)JLI_StrCat(JLI_StrCat(wanted, "/bin/"), progname); argv[0] = JLI_StringDup(progname); if (JLI_IsTraceLauncher()) { int i; printf("ReExec Command: %s (%s)\n", wanted, argv[0]); printf("ReExec Args:"); for (i = 1; argv[i] != NULL; i++) printf(" %s", argv[i]); printf("\n"); } JLI_TraceLauncher("TRACER_MARKER:About to EXEC\n"); //刷当前进程的标准输出/错误输出流 (void)fflush(stdout); (void)fflush(stderr); //执行新的可执行程序 execv(wanted, argv); JLI_ReportErrorMessageSys(JRE_ERROR12, wanted); exit(1); }