Чтобы изучить основной базовый исходный код JDK, вы должны освоить нативное использование

Java задняя часть
Чтобы изучить основной базовый исходный код JDK, вы должны освоить нативное использование

Мало знаний, большой вызов! Эта статья участвует в "   Необходимые знания для программистов   «Творческая деятельность

Эта статья также участвует "Проект "Звезда раскопок""   , чтобы выиграть творческие подарочные наборы и бросить вызов творческим поощрениям

❤️ Об авторе: Высококачественные создатели в области Java 🏆, сертификация эксперта по блогам CSDN 🏆, сертификация эксперта по облачному обмену Huawei 🏆 ❤️Техническая работа, она должна быть вознаграждена ❤️Нравится 👍 В избранное ⭐Посмотрите еще раз и сформируйте привычку

Сцены

Студенты, у которых есть желание исследовать, должны быть похожи на меня.При просмотре исходного кода JDK в конце будет собственный метод, похожий на следующий метод.

 /**
     * Gets the platform defined TimeZone ID.
     **/
    private static native String getSystemTimeZoneID(String javaHome);

Видеть этот родной означает, что ядро ​​раскопали.На данном этапе еще непонятно, как получить часовой пояс системы по умолчанию.Что делать?Код JDK может следовать только здесь.

Переключитесь на OpenJDK, метод загрузки исходного кода:git ee.com/mirrors/ о, квота…

что родное

Native — это компьютерная функция, а Native Method — это интерфейс Java для вызова кода, отличного от Java. Реализация метода реализована на языке, отличном от Java, таком как C или C++.

Как насчет нативного исходного кода?

Возьмите **private static native String getSystemTimeZoneID(String javaHome)** в качестве примера.

getSystemTimeZoneID方法所在的package java.util.TimeZone;

Как показано на рисунке, найдите метод getSystemTimeZoneID в TimeZone.c.

image-20210706233905997

image-20210706234052425

/*
 * Gets the platform defined TimeZone ID
 */
JNIEXPORT jstring JNICALL
Java_java_util_TimeZone_getSystemTimeZoneID(JNIEnv *env, jclass ign,
                                            jstring java_home, jstring country)
{
    const char *cname;
    const char *java_home_dir;
    char *javaTZ;

    if (java_home == NULL)
        return NULL;

    java_home_dir = JNU_GetStringPlatformChars(env, java_home, 0);
    if (java_home_dir == NULL)
        return NULL;

    if (country != NULL) {
        cname = JNU_GetStringPlatformChars(env, country, 0);
        /* ignore error cases for cname */
    } else {
        cname = NULL;
    }

    /*
     * Invoke platform dependent mapping function
     */
    javaTZ = findJavaTZ_md(java_home_dir, cname);

    free((void *)java_home_dir);
    if (cname != NULL) {
        free((void *)cname);
    }

    if (javaTZ != NULL) {
        jstring jstrJavaTZ = JNU_NewStringPlatform(env, javaTZ);
        free((void *)javaTZ);
        return jstrJavaTZ;
    }
    return NULL;
}

Ключевой момент: функции сопоставления вызовов, относящиеся к разным платформам

  /*
     * Invoke platform dependent mapping function
     */
    javaTZ = findJavaTZ_md(java_home_dir, cname);

При поиске метода findJavaTZ_md я обнаружил, что он существует в двух каталогах: solaris и windows.

image-20210706234905448

Проверьте разницу между этими двумя каталогами:

因为OpenJDK里,Java标准库和部分工具的源码repo(jdk目录)里,BSD和Linux的平台相关源码都是在solaris目录里的。
原本Sun JDK的源码里平台相关的目录就是从solaris和windows这两个目录开始的,后来Unix系的平台相关代码全都放在solaris目录下了,共用大部分代码。

作者:RednaxelaFX
链接:https://www.zhihu.com/question/58982441/answer/170264788
来源:知乎

Простое понимание:

В системе Windows используйте код JDK, скомпилированный в каталоге Windows.

На платформе unix используйте код JDK, скомпилированный в каталоге solaris.

Понять выполнение метода findJavaTZ_md в разных системах.

оконная система

/*
 * Detects the platform time zone which maps to a Java time zone ID.
 */
char *findJavaTZ_md(const char *java_home_dir, const char *country)
{
    char winZoneName[MAX_ZONE_CHAR];
    char winMapID[MAX_MAPID_LENGTH];
    char *std_timezone = NULL;
    int  result;

    winMapID[0] = 0;
    result = getWinTimeZone(winZoneName, winMapID);

    if (result != VALUE_UNKNOWN) {
        if (result == VALUE_GMTOFFSET) {
            std_timezone = _strdup(winZoneName);
        } else {
            std_timezone = matchJavaTZ(java_home_dir, result,
                                       winZoneName, winMapID, country);
        }
    }

    return std_timezone;
}

Комментарии написаны четко, получить текущий часовой пояс в реестре "Часовые пояса"

/*
 * Gets the current time zone entry in the "Time Zones" registry.
 */
static int getWinTimeZone(char *winZoneName, char *winMapID)
{
...
}

Как установить часовой пояс:

image-202107086550950

В то время откуда взялось значение выбора в области?Как было сказано выше, оно было получено из реестра.

Откройте реестр: Regedit-->

计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\

Unix-платформа

Комментарий к методу findJavaTz_md() очень ясен: сопоставьте идентификатор часового пояса платформы с идентификатором часового пояса Java.

/*
 * findJavaTZ_md() maps platform time zone ID to Java time zone ID
 * using <java_home>/lib/tzmappings. If the TZ value is not found, it
 * trys some libc implementation dependent mappings. If it still
 * can't map to a Java time zone ID, it falls back to the GMT+/-hh:mm
 * form. `country', which can be null, is not used for UNIX platforms.
 */
/*ARGSUSED1*/
char *
findJavaTZ_md(const char *java_home_dir, const char *country)
{
    char *tz;
    char *javatz = NULL;
    char *freetz = NULL;

    tz = getenv("TZ");

#ifdef __linux__
    if (tz == NULL) {
#else
#ifdef __solaris__
    if (tz == NULL || *tz == '\0') {
#endif
#endif
        tz = getPlatformTimeZoneID();
        freetz = tz;
    }

    /*
     * Remove any preceding ':'
     */
    if (tz != NULL && *tz == ':') {
        tz++;
    }

#ifdef __solaris__
    if (strcmp(tz, "localtime") == 0) {
        tz = getSolarisDefaultZoneID();
        freetz = tz;
    }
#endif

    if (tz != NULL) {
#ifdef __linux__
        /*
         * Ignore "posix/" prefix.
         */
        if (strncmp(tz, "posix/", 6) == 0) {
            tz += 6;
        }
#endif
        javatz = strdup(tz);
        if (freetz != NULL) {
            free((void *) freetz);
        }
    }
    return javatz;
}

шаг:

1. Используйте /lib/tzmappings. Если переменная «TZ» не найдена, перейдите к шагу 2.

2. tz = getPlatformTimeZoneID(); Выполнить сопоставление, специфичное для Linux, если оно найдено, вернуть идентификатор часового пояса, в противном случае вернуть null

[Linux] Centos7 изменяет метод часового пояса системного часового пояса:

timedatectl

image-202107086455780

Изменить часовой пояс

timedatectl  set-timezone Asia/Shanghai

image-2021070864438866

3. Сравните /etc/localtime с файлами в каталоге "/usr/share/zoneinfo. Если они совпадают, верните идентификатор часового пояса. Если нет, перейдите к шагу 4.

4. Вернуться к Гринвичу