正在运行的JVM是否检测到计算机时区的更改?

Ste*_*eod 15 java jvm

我找不到任何具体的文档来回答这个问题.

我写了一些简单的测试代码来解决OS X 10.12上Java 1.8上实际发生的事情:

public static void main(String[] _args) throws InterruptedException {
    while (true) {
        int calendarTimezoneOffset = Calendar.getInstance().get(Calendar.ZONE_OFFSET);
        System.out.println("calendarTimezoneOffset = " + calendarTimezoneOffset);

        ZoneOffset offset = ZonedDateTime.now().getOffset();
        System.out.println("offset = " + offset);

        Thread.sleep(1000);
    }
}
Run Code Online (Sandbox Code Playgroud)

旧方式(Calendar)和新方式(Java 8的日期和时间库)都没有检测到我在JVM运行时对操作系统的时区所做的任何更改.我需要停止并启动代码以获取更改的时区.

这是设计的吗?这是JVM实现和操作系统的可靠行为吗?

apa*_*gin 8

TimeZone.getDefault() 规范很清楚如何获得时区:

获取Java虚拟机的默认TimeZone.如果缓存的默认TimeZone可用,则返回其克隆.否则,该方法采用以下步骤来确定默认时区.

  • 如果user.timezone属性值可用,则使用user.timezone属性值作为默认时区ID.
  • 检测平台时区ID.平台时区和ID映射的来源可能随实现而变化.
  • 如果给定或检测到的时区ID未知,请使用GMT作为最后的手段.

从ID创建的默认TimeZone将被缓存,并返回其克隆.user.timezone属性值在返回时设置为ID.

文档说明该区域已缓存 ; 此方法受user.timezone系统属性的影响,反之亦然.

规范还说缓存通过TimeZone.setDefault(null)以下方式清除:

如果zone为null,则清除缓存的默认TimeZone.

也就是说,为了重新读取系统时区,你必须这样做

  1. 通过调用清除TimeZone缓存TimeZone.setDefault(null);
  2. user.timezone通过调用清除系统属性System.clearProperty("user.timezone");

尝试以下测试:

    while (true) {
        TimeZone.setDefault(null);
        System.clearProperty("user.timezone");

        System.out.println("Offset = " + TimeZone.getDefault().getRawOffset() / 3600);
        System.out.println("Zone ID = " + System.getProperty("user.timezone"));

        Thread.sleep(1000);
    }
Run Code Online (Sandbox Code Playgroud)