《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

猜你喜欢

转载自blog.csdn.net/weixin_37477523/article/details/88131408