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

Returning an Object from a conditional has wrong type

XMLWordPrintable

      A DESCRIPTION OF THE PROBLEM :
      For the conditional statement, there seems to be some sort of bug that is only showing up in Java 11 for some reason.


      For this source code:


        public static Object returnObject(Object n) {
          return n instanceof Number ? ((Number) n).longValue() : Double.NaN;
        }

        public static Object returnObject2(Object n) {
          if (n instanceof Number) {
            return ((Number) n).longValue();
          } else {
            return Double.NaN;
          }
        }


      We can see that the bytecode is different:


        public static java.lang.Object returnObject(java.lang.Object);
          Code:
             0: aload_0
             1: instanceof #15 // class java/lang/Number
             4: ifeq 18
             7: aload_0
             8: checkcast #15 // class java/lang/Number
            11: invokevirtual #16 // Method java/lang/Number.longValue:()J
            14: l2d
            15: goto 21
            18: ldc2_w #17 // double NaNd
            21: invokestatic #10 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
            24: areturn

        public static java.lang.Object returnObject2(java.lang.Object);
          Code:
             0: aload_0
             1: instanceof #15 // class java/lang/Number
             4: ifeq 18
             7: aload_0
             8: checkcast #15 // class java/lang/Number
            11: invokevirtual #16 // Method java/lang/Number.longValue:()J
            14: invokestatic #4 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
            17: areturn
            18: ldc2_w #17 // double NaNd
            21: invokestatic #10 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
            24: areturn


      Note that in instruction 14 of returnObject, there is a cast from long to double. This shows up in the tests where we are expecting a long but it is actually a double that is returned. I do not expect this cast to be there at all as I think Long is a valid return type for returnObject.

      I've reproduced this problem with 11.0.5 and 1.8.0_172.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      12
      false
      true
      false
      ACTUAL -
      12.0
      true
      false
      true


      ---------- BEGIN SOURCE ----------
      public class Test {

        public static void main (String[] args) {
          Object o = returnObject(Long.valueOf(12));
          System.out.println(o);
          System.out.println(o.equals(Double.valueOf(12.0)));
          System.out.println(o instanceof Long);
          System.out.println(o instanceof Double);
        }

        public static Object returnObject(Object n) {
          return n instanceof Number ? Long.valueOf(((Number) n).longValue()) : Double.NaN;
        }

        public static Object returnObject2(Object n) {
          if (n instanceof Number) {
            return ((Number) n).longValue();
          } else {
            return Double.NaN;
          }
        }

      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      The workaround is to split this up into an explicit if statement as shown in the source code and related bytecode.

            Unassigned Unassigned
            tongwan Andrew Wang
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: