转载

JVM加载TimeZone读取文件优先级实战分析

问题现象

前几天线上新上线一个Kafka Java Consumer程序,出现一个异常的问题,那就通过查看日志,数据写入到了Elasticsearch索引里面,但是前端查询不到数据。

最终通过和开发一起定位,是因为我们业务上的原因,默认数据时间戳问题,默认需要使用 UTC TimeZone ;但当运维用 date 命令看的时候,默认是UTC时区啊,为啥还是写错了呢?

因为我们线上维护的是 /etc/localtime 文件来保证时区问题,而且也是 UTC 时区,但是还是写入数据时间对不上,之后上线操作的同事说把 /etc/timezone 文件删除,然后重启消费者程序好了。

好了,这是为啥,虽然知道删除 /etc/timezone 文件后,业务数据写入正常了,但是这是为什么呢,下面我们就来一探究竟。

寻找真相

通常我遇到这种之前没有遇到的问题,都会借助Google搜索一把,搜索完成后,得到JVM加载时区文件顺序如下:

JVM加载TimeZone读取文件优先级实战分析
/etc/sysconfig/clock

中文参考链接: https://blog.csdn.net/zj380475045/article/details/72765936 http://www.360doc.com/content/12/1011/17/110467_240881174.shtml

英文参考链接: https://bugs.java.com/view_bug.do?bug_id=6456628

那按照搜索到的结果,跟我的情况不对啊,我们线上删除 /etc/timezone 文件就好了,所以肯定跟文件 /etc/timezone 有关啊,所以我感觉肯定跟操作系统和JAVA版本有关,SO我觉得实践一把,一定要把谜底揭开。

揭开谜底

环境 操作系统 JAVA版本
aliyun Centos6.5 1.8.0_25

如上表格是我线上环境情况,实践过程如下。

Java测试代码如下:

[root@Labhost2 src]# cat TimeTest.java 
import java.util.Date;
import java.util.TimeZone;

public class TimeTest {

    public static void main(String args[]) {
    long time = System.currentTimeMillis();
    String millis = Long.toString(time);
    Date date = new Date(time);
    System.out.println("Current time in milliseconds = " + millis + " => " + date.toString());
    System.out.println("Current time zone: " + TimeZone.getDefault().getID());
    }
}

[root@Labhost2 src]# javac TimeTest.java   # 生成测试类
[root@Labhost2 src]# ls
TimeTest.class  TimeTest.java

从搜索我们知道JVM读取时区跟系统变量 TZ 和文件 /etc/sysconfig/clock/etc/localtime 有关,我这里在加上我们删除的文件 /etc/timezone 一起来实践,验证过程如下:

原文  https://xiaozhuanlan.com/topic/1580672493
正文到此结束
Loading...