工作中,遇到一个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_2015openjdkjdksrcshare ativejavautilTimeZone.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_2015openjdkjdksrcsolaris ativejavautilTimeZone_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 == '