工作中,遇到一个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

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


												

Java读取系统默认时区的更多相关文章

  1. flash 读取系统默认编码

    java有类可以直接读取,但貌似flash没有. Charset.defaultCharset(); 但是浏览器里可以有. document.defaultCharset;//从当前的区域语言中获取默 ...

  2. 如何在Azure Websites中配置PHP从而改变系统默认时区

    Shirley_Wang  Tue, Mar 3 2015 7:29 AM Azure Website为我们提供了可高度扩展的网站部署平台.由于Website是PaaS(平台即服务)层的服务,当用户把 ...

  3. MTK 修改默认时区

    首先介绍应用程序修改 : AlarmManager mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); mA ...

  4. Java用System读取系统相关信息、环境变量——(六)

    package Java_Test; public class System1 { public static void main(String[] args) { // TODO Auto-gene ...

  5. Android系统移植与调试之------->如何修改Android的默认语言、默认时区

    修改device/other/TBDG1073/ system.prop文件 1.设置默认语言 找到device/other/TBDG1073/ system.prop文件,修改属性ro.produc ...

  6. Android 系统默认参数的修改

    转自: http://www.th7.cn/Program/Android/201505/447097.shtml 写在前面的话 一般在新项目开始之初,我们需要针对客户需求进行各种系统默认属性的配置, ...

  7. Java消息系统简单设计与实现

    前言:由于导师在我的毕设项目里加了消息系统(本来想水水就过的..),没办法...来稍微研究研究吧..简单简单... 需求分析 我的毕设是一个博客系统,类似于简书这样的,所以消息系统也类似,在用户的消息 ...

  8. 通过系统自带的内容提供器(ContentResolver)读取系统的通讯录,并设置点击事件

    1.布局 主布局只有一个listview,用来显示电话簿的名字和手机号码 <?xml version="1.0" encoding="utf-8"?> ...

  9. Android系统默认设置

    修改Settings源码,可修改系统设置项,Settings数据被存放于com.android.providers.settings/databases/settings.db中,如果想修改系统启动后 ...

随机推荐

  1. 给PDF文件创建书签,实现快速导航

    当文档中的页码比较多的情况下,使用目录进行导航是一个很好用的方法,为文档内容制作目录,方便快速查找目标内容.除了内容的快速导航,书签还能指明不同书签的层级关系,展现文档的结构. 图1:书签的功能 一. ...

  2. 如何查看CDR文件是出自哪个版本?

    如何才能知道某个cdr文件用哪个版本的CorelDRAW软件打开?网上CorelDRAW软件有很多版本,都不知该下哪个了?这是我听到大家问道最多的问题,这是因为CDR低版本软件打不开高版本文件. 方法 ...

  3. hashmap(有空可以看看算法这本书中对于这部分的实现,很有道理)

    //转载:https://baijiahao.baidu.com/s?id=1618550070727689060&wfr=spider&for=pc 1.为什么用HashMap? H ...

  4. windows创建隐藏用户的powershell脚本

    通过保存并重新注册已删除用户的注册表的方式来隐藏用户,未登录时登陆界面不可见,登陆后可见 方法详情见: https://www.k0rz3n.com/2018/06/26/windows%E6%B8% ...

  5. python测试代码

    前言: 编写函数或者类时,需要编写测试代码,来保证其的功能运行是否按预期的那样工作.在程序添加新的代码时,用来测试是否会破坏本身的功能. 我们使用python自带的unittest模块来测试代码. 编 ...

  6. Python学习系列之列表(十一)

    一.为什么需要列表 变量可以存储一个元素,而列表是一个"大容器"可以存储N多个元素,程序可以方便地对这些数据进行整体操作 列表相当于其它语言中的数组 二.列表的创建1.列表需要使用 ...

  7. C语言讲义——链表的实现

    节点(结构体描述) struct Node { int _id; char s[50]; struct Node* pre;// 指向前一个节点的地址 struct Node* next;// 指向下 ...

  8. 【mq读书笔记】mq消息消费

    消息消费以组的的模式开展: 一个消费组内可以包含多个消费者,每一个消费组可订阅多个主题: 消费组之间有集群模式与广播模式两种消费模式:集群模式-主题下的同一条消息只允许被其中一个消费者消费.广播模式- ...

  9. Error:Execution failed for task ':app:compileDebugAidl'. > java.lang.IllegalStateException: aidl is missing from '/Users/renguodong/Library/Android/sdk/build-tools/26.0.2/aidl'

    错误信息:Error:Execution failed for task ':app:compileDebugAidl'. > java.lang.IllegalStateException: ...

  10. python核心高级学习总结4-------python实现进程通信

    Queue的使用 Queue在数据结构中也接触过,在操作系统里面叫消息队列. 使用示例 # coding=utf-8 from multiprocessing import Queue q = Que ...