JDK-8133022 : Instant.toEpochMilli() silently overflows
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.time
  • Affected Version: 8u45,9
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_8
  • CPU: x86
  • Submitted: 2015-06-11
  • Updated: 2016-01-14
  • Resolved: 2015-08-06
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u72Fixed 9 b77Fixed
Description
FULL PRODUCT VERSION :
1.8.0_45-b15

ADDITIONAL OS VERSION INFORMATION :
Any OS

A DESCRIPTION OF THE PROBLEM :
This code should throw an ArithmeticException but silently overflows:

    Instant tooMuch = Instant.ofEpochSecond(Long.MAX_VALUE / 1000, 809_000_000);
    System.out.println(tooMuch.toEpochMilli()); //prints -9223372036854775807

The problem is in the code of toEpochMilli:

    public long toEpochMilli() {
        long millis = Math.multiplyExact(seconds, 1000);
        return millis + nanos / 1000_000;
    }

which should probably be:

    public long toEpochMilli() {
        long millis = Math.multiplyExact(seconds, 1000);
        return Math.addExact(millis, nanos / 1000_000);
    }

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The code should throw an ArithmeticException
ACTUAL -
The result is a negative number due to overflow

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
  public static void main(String args[]) {
    Instant tooMuch = Instant.ofEpochSecond(Long.MAX_VALUE / 1000, 809_000_000);
    System.out.println(tooMuch.toEpochMilli()); //prints -9223372036854775807
  }
---------- END SOURCE ----------


Comments
Another test case: Instant inst = Instant.ofEpochSecond(-9223372036854776L, 1); System.out.println(inst.toEpochMilli());
06-08-2015

Yes, this looks like a bug. The proposed fix would be the correct one.
05-08-2015

- Run the attached test case in Windows 7. - Checked this for JDK 8u45, 8u51, 8u60 ea b26 and 9 ea b75 and could conform the issue. - Output with JDK 8u51: > java Main -9223372036854775807 - Moving this up for further evaluation.
05-08-2015