Skip to content

Instant.now() 在 jdk1.8 和 jdk11 的区别 #73

Description

@techiall

使用 jdk1.8 和 jdk11 编译下面这段代码,发现输出结果不一样。

import java.time.Instant;

/**
 * @author techial
 */
public class Main {
    public static void main(String[] args) {
        System.out.println(Instant.now());
    }
}

两个 jdk 版本输出的结果如下:

$ java -version
openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.7+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.7+10, mixed mode)


$ javac Main.java
$ java Main
2020-06-11T13:17:59.711337Z


$ java -version
java version "1.8.0_212"
Java(TM) SE Runtime Environment (build 1.8.0_212-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.212-b10, mixed mode)

$ javac Main.java
$ java Main      
2020-06-11T13:18:19.622Z

发现 jdk11 输出的精度变高了,Instant.now() 的实现是调用了 Clock.systemUTC().instant();,再点击 systemUTC() 方法,会发现 jdk11 和 jdk1.8 的实现逻辑不一样。

    /**
     * Obtains the current instant from the system clock.
     * <p>
     * This will query the {@link Clock#systemUTC() system UTC clock} to
     * obtain the current instant.
     * <p>
     * Using this method will prevent the ability to use an alternate time-source for
     * testing because the clock is effectively hard-coded.
     *
     * @return the current instant using the system clock, not null
     */
    public static Instant now() {
        return Clock.systemUTC().instant();
    }

jdk1.8 实现如下,只粘贴相关代码段。

    public static Clock systemUTC() {
        return new SystemClock(ZoneOffset.UTC);
    }

    static final class SystemClock extends Clock implements Serializable {
        private static final long serialVersionUID = 6740630888130243051L;
        private final ZoneId zone;

        SystemClock(ZoneId zone) {
            this.zone = zone;
        }
    ...

jdk11 实现如下,只粘贴相关代码段。

    public static Clock systemUTC() {
        return SystemClock.UTC;
    }

    static final class SystemClock extends Clock implements Serializable {
        private static final long serialVersionUID = 6740630888130243051L;
        private static final long OFFSET_SEED =
                System.currentTimeMillis()/1000 - 1024; // initial offest
        static final SystemClock UTC = new SystemClock(ZoneOffset.UTC);

        private final ZoneId zone;
        // We don't actually need a volatile here.
        // We don't care if offset is set or read concurrently by multiple
        // threads - we just need a value which is 'recent enough' - in other
        // words something that has been updated at least once in the last
        // 2^32 secs (~136 years). And even if we by chance see an invalid
        // offset, the worst that can happen is that we will get a -1 value
        // from getNanoTimeAdjustment, forcing us to update the offset
        // once again.
        private transient long offset;

        SystemClock(ZoneId zone) {
            this.zone = zone;
            this.offset = OFFSET_SEED;
        }

后来去网上查了一下,发现从 jdk9 开始后,提高了 java.time.Clock.systemUTC() 这个方法的精度。

Instant.now() 精度由毫秒提升到了微秒。

https://bugs.openjdk.java.net/browse/JDK-8068730

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions