Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8146747

java.time.Duration.toNanos() and toMillis() exception on negative durations

    Details

    • Subcomponent:
    • Resolved In Build:
      b105
    • CPU:
      generic
    • OS:
      generic

      Description

      FULL PRODUCT VERSION :
      java version "1.8.0_66"
      Java(TM) SE Runtime Environment (build 1.8.0_66-b18)
      Java HotSpot(TM) 64-Bit Server VM (build 25.66-b18, mixed mode)

      A DESCRIPTION OF THE PROBLEM :
      java.time.Duration.toNanos() and toMillis() throw an ArithmeticException on an intermediate calculation when the duration is very close to, but greater than Long.MIN_VALUE nanoseconds or milliseconds, respectively.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Duration.ofNanos(Long.MIN_VALUE).toNanos();

      Duration.ofMillis(Long.MIN_VALUE).toMillis();


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Expected result from each statement is Long.MIN_VALUE.
      ACTUAL -
      Both the statements throw ArithmeticException.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      public class Bug {
          public static void main(String[] args) {
              // uncomment following line for toNanos() bug
              // Duration.ofNanos(Long.MIN_VALUE).toNanos();
              Duration.ofMillis(Long.MIN_VALUE).toMillis();
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      The following implementations of toNanos() and toMillis() fix the problem:

          public long toMillis() {
              long millis;
              if (isNegative()) {
                  millis = Math.multiplyExact(seconds + 1, 1000);
                  millis = Math.addExact(millis, nanos / 1000_000 - 1000);
              }
              else {
                  millis = Math.multiplyExact(seconds, 1000);
                  millis = Math.addExact(millis, nanos / 1000_000);
              }
              return millis;
          }

          public long toNanos() {
              long totalNanos;
              if (isNegative()) {
                  totalNanos = Math.multiplyExact(seconds() + 1, NANOS_PER_SECOND);
                  totalNanos = Math.addExact(totalNanos, nanos - NANOS_PER_SECOND);
              }
              else {
                  totalNanos = Math.multiplyExact(seconds, NANOS_PER_SECOND);
                  totalNanos = Math.addExact(totalNanos, nanos);
              }
              return totalNanos;
          }


        Activity

        Hide
        psonal Pallavi Sonal added a comment -
        Attached test case executed on:
        JDK 8u66 - Fail
        JDK 9 ea b93 - Fail

        Following is the output :
        Exception in thread "main" java.lang.ArithmeticException: long overflow
                at java.lang.Math.multiplyExact(Math.java:931)
                at java.time.Duration.toNanos(Duration.java:1198)
                at JI9028401.main(JI9028401.java:6)
        Show
        psonal Pallavi Sonal added a comment - Attached test case executed on: JDK 8u66 - Fail JDK 9 ea b93 - Fail Following is the output : Exception in thread "main" java.lang.ArithmeticException: long overflow         at java.lang.Math.multiplyExact(Math.java:931)         at java.time.Duration.toNanos(Duration.java:1198)         at JI9028401.main(JI9028401.java:6)
        Hide
        ntv Nadeesh Tv (Inactive) added a comment - - edited
        In my opinion, it's a valid bug because
        there is a chance of over flow in public static long multiplyExact(long x, long y) {}
        Show
        ntv Nadeesh Tv (Inactive) added a comment - - edited In my opinion, it's a valid bug because there is a chance of over flow in public static long multiplyExact(long x, long y) {}
        Hide
        rriggs Roger Riggs added a comment -
        Yes, seems reasonable
        Show
        rriggs Roger Riggs added a comment - Yes, seems reasonable
        Hide
        scolebourne Stephen Colebourne added a comment -
        The behaviour of the java.time methods is clear. If they can succeed without overflow they should. Otherwise an exception should be thrown. As such, it looks like a bug to be fixed.
        Show
        scolebourne Stephen Colebourne added a comment - The behaviour of the java.time methods is clear. If they can succeed without overflow they should. Otherwise an exception should be thrown. As such, it looks like a bug to be fixed.
        Hide
        hgupdate HG Updates added a comment -
        URL: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/3e5970acb0a7
        User: rriggs
        Date: 2016-02-08 14:57:13 +0000
        Show
        hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/3e5970acb0a7 User: rriggs Date: 2016-02-08 14:57:13 +0000
        Hide
        hgupdate HG Updates added a comment -
        URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/3e5970acb0a7
        User: lana
        Date: 2016-02-10 21:55:24 +0000
        Show
        hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/3e5970acb0a7 User: lana Date: 2016-02-10 21:55:24 +0000

          People

          • Assignee:
            ntv Nadeesh Tv (Inactive)
            Reporter:
            webbuggrp Webbug Group
          • Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: