Jvm的时区问题

最近发现在一台开发机上java程序启动后时间不对,比系统时间慢八小时,检查系统时间却发现是正确的…

有俩种解决方案,方案一:

//程序内设置TimeZone
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
class Test{
    public static void main(String[] args){
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
        df.setTimeZone(tz);
        System.out.println(df.format(new Date()));
        System.out.println(new Date().toString());
    }
}

result:

2014-09-02 23:03:25
Tue Sep 02 15:03:25 UTC 2014

方案二:

在程序的启动脚本里加上时区参数
-Duser.timezone=Asia/Shanghai

打印结果可以看出是时区不正确,jvm获取到的时区为UTC,而正确的时间应为CST(北京时间),方案二显然更加灵活但也治标不治本。
接下来检查当前系统属性

//遍历当前系统属性
final Properties p = System.getProperties();
final Enumeration e = p.keys();
while (e.hasMoreElements()) {
    final String prt = (String) e.nextElement();
    final String prtvalue = System.getProperty(prt);
    System.out.println(prt + ":" + prtvalue);
}

可以发现如下参数:

...
java.vm.specification.vendor:Oracle Corporation
os.name:Linux
sun.jnu.encoding:UTF-8
java.library.path:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.specification.name:Java Platform API Specification
java.class.version:51.0
sun.management.compiler:HotSpot 64-Bit Tiered Compilers
os.version:3.11.0-15-generic
user.home:/root
user.timezone:Etc/UTC
java.awt.printerjob:sun.print.PSPrinterJob
file.encoding:UTF-8
java.specification.version:1.7
java.class.path:/home/app/jdk1.7.0_67/lib:.
user.name:root
java.vm.specification.version:1.7
sun.java.command:Test
java.home:/home/app/jdk1.7.0_67/jre
...

本地使用的jdk环境是64-Bit jdk7U67,系统环境64Bit Ubuntu 12.04。
终极方案:修改系统的时区为「Asia/Shanghai」。

cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime