工作中,遇到一个Java读取默认时区的问题,后来看了openjdk的源码,大致整理一下过程

public class Test {
public void test(){
TimeZone.getDefault();
}
}

TimeZone.getDefault()会跳到下面代码:

    private static synchronized TimeZone setDefaultZone() {
TimeZone tz;
// get the time zone ID from the system properties
String zoneID = AccessController.doPrivileged(
new GetPropertyAction("user.timezone")); // if the time zone ID is not set (yet), perform the
// platform to Java time zone ID mapping.
if (zoneID == null || zoneID.isEmpty()) {
String javaHome = AccessController.doPrivileged(
new GetPropertyAction("java.home"));
try {
zoneID = getSystemTimeZoneID(javaHome);
if (zoneID == null) {
zoneID = GMT_ID;
}
} catch (NullPointerException e) {
zoneID = GMT_ID;
}
} // Get the time zone for zoneID. But not fall back to
// "GMT" here.
tz = getTimeZone(zoneID, false); if (tz == null) {
// If the given zone ID is unknown in Java, try to
// get the GMT-offset-based time zone ID,
// a.k.a. custom time zone ID (e.g., "GMT-08:00").
String gmtOffsetID = getSystemGMTOffsetID();
if (gmtOffsetID != null) {
zoneID = gmtOffsetID;
}
tz = getTimeZone(zoneID, true);
}
assert tz != null; final String id = zoneID;
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
System.setProperty("user.timezone", id);
return null;
}
}); defaultTimeZone = tz;
return tz;
}

如果没有设置时区的话,会进入一个native方法

zoneID = getSystemTimeZoneID(javaHome);

这个方法的实现,可以参考

openjdk-8u40-src-b25-10_feb_2015\openjdk\jdk\src\share\native\java\util\TimeZone.c
JNIEXPORT jstring JNICALL
Java_java_util_TimeZone_getSystemTimeZoneID(JNIEnv *env, jclass ign,
jstring java_home)
{
const char *java_home_dir;
char *javaTZ;
jstring jstrJavaTZ = NULL; CHECK_NULL_RETURN(java_home, NULL); java_home_dir = JNU_GetStringPlatformChars(env, java_home, 0);
CHECK_NULL_RETURN(java_home_dir, NULL); /*
* Invoke platform dependent mapping function
*/
javaTZ = findJavaTZ_md(java_home_dir);
if (javaTZ != NULL) {
jstrJavaTZ = JNU_NewStringPlatform(env, javaTZ);
free((void *)javaTZ);
} JNU_ReleaseStringPlatformChars(env, java_home, java_home_dir);
return jstrJavaTZ;
}

主要看:

javaTZ = findJavaTZ_md(java_home_dir);

继续参考,下面TimeZone_md.c文件,可以知道find_JavaTZ_md方法的实现

openjdk-8u40-src-b25-10_feb_2015\openjdk\jdk\src\solaris\native\java\util\TimeZone_md.c
char *
findJavaTZ_md(const char *java_home_dir)
{
char *tz;
char *javatz = NULL;
char *freetz = NULL; tz = getenv("TZ"); #if defined(__linux__) || defined(_ALLBSD_SOURCE)
if (tz == NULL) {
#else
#if defined (__solaris__) || defined(_AIX)
if (tz == NULL || *tz == '\0') {
#endif
#endif
tz = getPlatformTimeZoneID();
freetz = tz;
} /*
* Remove any preceding ':'
*/
if (tz != NULL && *tz == ':') {
tz++;
} #ifdef __solaris__
if (tz != NULL && 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);
} #ifdef _AIX
freetz = mapPlatformToJavaTimezone(java_home_dir, javatz);
if (javatz != NULL) {
free((void *) javatz);
}
javatz = freetz;
#endif
} return javatz;
}

tz = getPlatformTimeZoneID(),这个函数内容,就不贴了,可以自己看下,总计起来,在Linux系统上,大概过程为以下几步:

1.先找“TZ”变量,没有,到2,

2.读/etc/timezone,没有到3,

3.比较/etc/localtime文件与"/usr/share/zoneinfo目录下所有时区文件,如果有一致的,就为该时区,如果没有,到4,

4.默认为标准GMT

如有不正确的地方,欢迎指正!


												

最新文章

  1. 在使用 HttpWebRequest Post数据时候返回 400错误
  2. git clone Linux 源码并切换TAG
  3. Web攻防之XSS,CSRF,SQL注入
  4. 如何在 ASP.NET MVC 中集成 AngularJS(1)
  5. Spring3 MVC入门示例
  6. Action类为何要 extends ActionSupport
  7. 1137. Bus Routes(dfs)
  8. 两个数组a[N],b[N],其中A[N]的各个元素值已知,现给b[i]赋值,b[i] = a[0]*a[1]*a[2]…*a[N-1]/a[i];
  9. Java网络编程(TCP协议-服务端和客户端交互)
  10. js replace in multi-line string
  11. Java---计算机贷款支付额计算(用对话框实现)
  12. sshuttle基于VPN的透明代理,安全连接
  13. iOS 7 新特性
  14. kettle新建资源库(4)
  15. Java基础 -- Collection和Iterator接口的实现
  16. Mybatis注解和配置文件命名规范所引发的问题
  17. 我写的Java相关的文章
  18. 转载-MySQL binlog三种模式及设置方法
  19. Altium Designer重装后图标都变白板或都变一样的解决方法
  20. libdl.so 动态库加载、查找

热门文章

  1. bWAPP----HTML Injection - Reflected (POST)
  2. Mac电脑疑似中毒该怎么应对处理
  3. 【PYTEST】第二章编写测试函数
  4. DNS系列—dig命令的使用
  5. TkMybatis 是什么?
  6. kali修改配置文件后并保存
  7. 团队作业第六次——Beta冲刺
  8. 微信小程序里如何使用npm?小程序集成友盟举例
  9. charles抓包使用
  10. MapReduce怎么优雅地实现全局排序