《jdk8u源码分析》6.1.GetJREPath
作者:互联网
src/windows/bin/java_md.c::GetJREPath
/*
* Find path to JRE based on .exe's location or registry settings.
*/
jboolean
GetJREPath(char *path, jint pathsize)
{
char javadll[MAXPATHLEN];
struct stat s;
//当前应用程序下存在jre,先加载应用程序下面的jre
//获取当前应用主目录,移除\*.exe,如果存在exe文件父目录(Eg: \bin)继续移除,并赋值给path
if (GetApplicationHome(path, pathsize)) {
/* Is JRE co-located with the application? */
//拼接java.dll完全路径: %APP_HOME%\bin\java.dll
JLI_Snprintf(javadll, sizeof(javadll), "%s\\bin\\" JAVA_DLL, path);
//获取文件相关信息并储存到结构体stat s中,如果成功返回0,失败返回-1
if (stat(javadll, &s) == 0) {
JLI_TraceLauncher("JRE path is %s\n", path);
return JNI_TRUE;
}
//如果%APP_HOME%\bin\java.dll不存在,继续搜索%APP_HOME%\jre\bin\java.dll
/* ensure storage for path + \jre + NULL */
//判断path的长度是否符合要求,为下面拼接jre做准备
if ((JLI_StrLen(path) + 4 + 1) > pathsize) {
JLI_TraceLauncher("Insufficient space to store JRE path\n");
return JNI_FALSE;
}
/* Does this app ship a private JRE in <apphome>\jre directory? */
//拼接java.dll完全路径:%APP_HOME%\jre\bin\java.dll
JLI_Snprintf(javadll, sizeof (javadll), "%s\\jre\\bin\\" JAVA_DLL, path);
//获取文件相关信息并储存到结构体stat s中,如果成功返回0,失败返回-1
if (stat(javadll, &s) == 0) {
//拼接jre目录
JLI_StrCat(path, "\\jre");
JLI_TraceLauncher("JRE path is %s\n", path);
return JNI_TRUE;
}
}
//如果当前目录下不存在jre环境,则获取注册表中的jre配置目录:
//注册表子键:HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\${version}
//值项:JavaHome 的值,e.g:C:\Tools\Java\open-jre1.8.0_202
/* Look for a public JRE on this machine. */
if (GetPublicJREHome(path, pathsize)) {
JLI_TraceLauncher("JRE path is %s\n", path);
return JNI_TRUE;
}
//"Error: could not find "%APP_HOME%\
JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
return JNI_FALSE;
}
src/windows/bin/java_md.c::GetApplicationHome
/*
* If app is "c:\foo\bin\javac", then put "c:\foo" into buf.
*/
jboolean
GetApplicationHome(char *buf, jint bufsize)
{
char *cp;
GetModuleFileName(0, buf, bufsize);
//搜索反斜杠在buf中最后一次出现的位置,并赋值为'\0',即移除最后一个反斜杠及以后的字符串
*JLI_StrRChr(buf, '\\') = '\0'; /* remove .exe file name */
//继续搜索(判定buf中是否还包含反斜杠)
if ((cp = JLI_StrRChr(buf, '\\')) == 0) {
/* This happens if the application is in a drive root, and
* there is no bin directory. */
buf[0] = '\0';
return JNI_FALSE;
}
//如果存在继续移除
*cp = '\0'; /* remove the bin\ part */
return JNI_TRUE;
}
src/windows/bin/java_md.c::GetPublicJREHome
static jboolean
GetPublicJREHome(char *buf, jint bufsize)
{
HKEY key, subkey;
char version[MAXPATHLEN];
/*
* Note: There is a very similar implementation of the following
* registry reading code in the Windows java control panel (javacp.cpl).
* If there are bugs here, a similar bug probably exists there. Hence,
* changes here require inspection there.
*/
/* Find the current version of the JRE */
//打开注册表子键JRE_KEY: HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, JRE_KEY, 0, KEY_READ, &key) != 0) {
//"Error: opening registry key '%s'"
JLI_ReportErrorMessage(REG_ERROR1, JRE_KEY);
return JNI_FALSE;
}
//读取JRE_KEY下的值项:CurrentVersion 的值,存储到version中
if (!GetStringFromRegistry(key, "CurrentVersion",
version, sizeof(version))) {
//"Error: Failed reading value of registry key:\n\t%s\\CurrentVersion"
JLI_ReportErrorMessage(REG_ERROR2, JRE_KEY);
RegCloseKey(key);
return JNI_FALSE;
}
//判断version与当DOT_VERSION是否匹配
if (JLI_StrCmp(version, GetDotVersion()) != 0) {
//"Error: Registry key '%s'\\CurrentVersion'\nhas value '%s', but '%s' is required."
JLI_ReportErrorMessage(REG_ERROR3, JRE_KEY, version, GetDotVersion()
);
RegCloseKey(key);
return JNI_FALSE;
}
/* Find directory where the current version is installed. */
//打开注册表子键:Java Runtime Environment\\${version}
if (RegOpenKeyEx(key, version, 0, KEY_READ, &subkey) != 0) {
////"Error: opening registry key '%s'"
JLI_ReportErrorMessage(REG_ERROR1, JRE_KEY, version);
RegCloseKey(key);
return JNI_FALSE;
}
//读取注册表子键:Java Runtime Environment\\${version} 下的值项:JavaHome
//并将值存储到buf中,作为返回值返回,e.g.:C:\Tools\Java\open-jre1.8.0_202
if (!GetStringFromRegistry(subkey, "JavaHome", buf, bufsize)) {
//"Failed reading value of registry key:\n\t%s\\%s\\JavaHome"
JLI_ReportErrorMessage(REG_ERROR4, JRE_KEY, version);
RegCloseKey(key);
RegCloseKey(subkey);
return JNI_FALSE;
}
if (JLI_IsTraceLauncher()) {
char micro[MAXPATHLEN];
//读取注册表子键:Java Runtime Environment\\${version} 下的值项:MicroVersion
//并将值存储到micro中
if (!GetStringFromRegistry(subkey, "MicroVersion", micro,
sizeof(micro))) {
printf("Warning: Can't read MicroVersion\n");
micro[0] = '\0';
}
printf("Version major.minor.micro = %s.%s\n", version, micro);
}
RegCloseKey(key);
RegCloseKey(subkey);
return JNI_TRUE;
}
src/windows/bin/java_md.c::GetStringFromRegistry
static jboolean
GetStringFromRegistry(HKEY key, const char *name, char *buf, jint bufsize)
{
DWORD type, size;
//搜索注册表key下面名为name && 数据类型为REG_SZ的值项,并将值存入buf中
if (RegQueryValueEx(key, name, 0, &type, 0, &size) == 0
&& type == REG_SZ
&& (size < (unsigned int)bufsize)) {
if (RegQueryValueEx(key, name, 0, 0, buf, &size) == 0) {
return JNI_TRUE;
}
}
return JNI_FALSE;
}
注册表主要数据类型:
显示类型 | 数据类型 | 说明 |
---|---|---|
REG_SZ | 字符串 | 文本字符串 |
REG_MULTI_SZ | 多字符串 | 含有多个文本值的字符串 |
REG_BINARY | 二进制数 | 二进制值,以十六进制显示 |
REG_DWORD | 双字 | 一个32位的二进制值,显示为8位的十六进制值 |
src/windows/bin/java_md.c::GetDotVersion
const char*
GetDotVersion()
{
return _dVersion;
}
src/share/bin/defines.h
#if defined(JDK_MAJOR_VERSION) && defined(JDK_MINOR_VERSION)
#define DOT_VERSION JDK_MAJOR_VERSION "." JDK_MINOR_VERSION
#else
/* make sure the compilation fails */
#error "JDK_MAJOR_VERSION and JDK_MINOR_VERSION must be defined"
#endif
标签:bin,GetJREPath,version,JRE,源码,jdk8u,key,path,JLI 来源: https://blog.csdn.net/weixin_37477523/article/details/88131408