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