bugGNU Octave - Bugs: bug #51804, java-9: java.base/java.lang.Double...

 
 

bug #51804: java-9: java.base/java.lang.Double cannot be cast to java.base/java.lang.Integer

Submitted by:  Dmitri A. Sergatskov <dasergatskov>
Submitted on:  Sun 20 Aug 2017 06:22:45 PM UTC  
 
Category:  Test Suite Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Unexpected Error
Status:  Need Info Assigned to:  None
Originator Name:  Open/Closed:  Open
Release:  dev Operating System:  GNU/Linux

Add a New Comment (Rich Markup)
   

You are not logged in

Please log in, so followups can be emailed to you.

 

( Jump to the original submission)

Thu 19 Jul 2018 06:39:59 AM UTC, comment #14: 

> It's not documented, I can only guess that the Comparable<T> interface also defines a compareTo(Object) method that internally tries to cast the object to type T.


Basically, yes: That "compareTo(Object)" method is a "bridge method" implicitly synthesized by the Java compiler to support the "type erasure" mechanism of Java generics. Internally, it'll do the cast and pass the call on to the specialized "compareObject(Integer)" that the java.lang.Integer source code actually defines. See http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ102 if you care about the details.

You can see the details using "javap" to disassemble the class files in the JRE's `rt.jar` if you're curious. Here's what `compareTo(Object)` looks like in JDK 8:

  public int compareTo(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #1                  // class java/lang/Integer
       5: invokevirtual #96                 // Method compareTo:(Ljava/lang/Integer;)I
       8: ireturn

I don't think you can rely on the ordering of the Java methods coming back from java.lang.Class's Reflection methods like getMethods() and getDeclaredMethods(). That's implementation-dependent. And it looks like the implementation-dependent ordering changed between JVM versions here.

From the documentation for java.lang.Class.getMethods :

> The elements in the returned array are not sorted and are not in any particular order.


You'll need to sort the methods by degree of specialization or matching to the input types to determine what sort of conversion to do and which method to call. Non-trivial.

Andrew Janke <apjanke>
Tue 24 Apr 2018 05:34:58 PM UTC, comment #13: 

In bug #53728, this same conversion error was reported for the Oracle Java 7 runtime, but with Short instead of Integer.

Mike Miller <mtmiller>
Project Administrator
Thu 22 Mar 2018 11:36:36 PM UTC, comment #12: 

I get pretty much the same with dev branch (47f25e164ab1):

octave:1> test libinterp/octave-value/ov-java.cc-tst
***** testif HAVE_JAVA; usejava ("jvm") <51804>
n = javaObject ("java.lang.Integer", 1.35);
assert (n.compareTo (0), 1);
assert (n.compareTo (1), 0);
assert (n.compareTo (2), -1);
!!!!! known bug: http://octave.org/testfailure/?51804
[java] java.lang.ClassCastException: java.base/java.lang.Double cannot be cast to java.base/java.lang.Integer
PASSES 15 out of 16 tests (1 known bug)
octave:2> n = javaObject ("java.lang.Integer", 1.35)
n =

<Java object: java.lang.Integer>

octave:3> assert (n.compareTo (0), 1)
error: [java] java.lang.ClassCastException: java.base/java.lang.Double cannot be cast to java.base/java.lang.Integer
octave:3> __octave_config_info__ ("hg_id")
ans = 47f25e164ab1
octave:4> frame = javaObject ("java.awt.Frame");
octave:5>

So it looks to me the difference is due to java version (revision).

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Thu 22 Mar 2018 11:18:41 PM UTC, comment #11: 

Is this with dev or with stable branch?

I can get fedora buildbots to build with java-9 as well (all I have to do is set JAVA_HOME) is this is of more interest.

Dmitri.

Dmitri A. Sergatskov <dasergatskov>
Thu 22 Mar 2018 11:16:22 PM UTC, comment #10: 

I just updated my buildbot to Java 9

http://buildbot.octave.org:8010/builders/gcc-6-debian/builds/1475/steps/test/logs/stdio

I get a different test failure, that is bug #53428.

But the test that used to fail for me now passes.

$ ./run-octave -q
>> n = javaObject ("java.lang.Integer", 1.35)
>> assert (n.compareTo (0), 1)
>> assert (n.compareTo (0), 1)
>> assert (n.compareTo (2), -1)

no errors.

Mike Miller <mtmiller>
Project Administrator
Thu 22 Mar 2018 11:10:00 PM UTC, comment #9: 

I still am getting this error with stable

octave:1> n = javaObject ("java.lang.Integer", 1.35)
n =

<Java object: java.lang.Integer>

octave:2> assert (n.compareTo (0), 1)
error: [java] java.lang.ClassCastException: java.base/java.lang.Double cannot be cast to java.base/java.lang.Integer
octave:2> __octave_config_info__ ("hg_id")
ans = 2b040946dc69

java-9-openjdk-9.0.4.11-4.fc27.x86_64

(so it also Xfails make check):

Dmitri A. Sergatskov <dasergatskov>
Thu 22 Mar 2018 07:12:18 PM UTC, comment #8: 

I can't reproduce this test failure anymore with the version of Java 9 in Debian unstable (9.0.4+12-Debian-2).

Dmitri, is this error still occurring for you on Fedora with your version of Java?

Mike Miller <mtmiller>
Project Administrator
Sun 20 Aug 2017 09:12:58 PM UTC, comment #7: 

It's not documented, I can only guess that the Comparable<T> interface also defines a compareTo(Object) method that internally tries to cast the object to type T.

Mike Miller <mtmiller>
Project Administrator
Sun 20 Aug 2017 08:59:59 PM UTC, comment #6: 

Ok, this may be the problem

x = javaObject ("java.lang.Integer", 0)
methods (x)

With Java 8, the list contains

  [1,13] = int compareTo(java.lang.Integer)
  [1,14] = int compareTo(java.lang.Object)

in that order. So when Octave iterates through the available methods, it finds the Integer one first, and everything works as expected. With Java 9, I get the following

  [1,13] = int compareTo(java.lang.Object)
  [1,14] = int compareTo(java.lang.Integer)

in the opposite order. Octave finds the one that takes an Object first, assumes that that should work when given a double-valued argument, and calls it. If that method actually exists and works, then this should work. But it's like Java is reporting that this compareTo(Object) method exists, but when it's called it is actually calling the one that takes an Integer.

Mike Miller <mtmiller>
Project Administrator
Sun 20 Aug 2017 08:45:39 PM UTC, comment #5: 

I don't see any difference in the API, both Java 8 and 9 say that java.lang.Integer.compareTo takes java.lang.Integer as an argument. However, when Octave is inspecting the runtime for the method "compareTo", the result says that it takes an argument of type java.lang.Object, not Integer. Octave doesn't do any casting because it doesn't think it has to, but then when the method is called the exception is thrown.

Someone might want to look into the Java 9 runtime in more detail and find out why this is happening. I think it will take writing some Java code to iterate over the available methods in the Integer class and see what's different.

Mike Miller <mtmiller>
Project Administrator
Sun 20 Aug 2017 06:37:59 PM UTC, comment #4: 

Sorry -- the comments 1 and 2 crossed over in the ether.
I am looking at

https://docs.oracle.com/javase/9/whatsnew/toc.htm#JSNEW-GUID-0CA9D45F-31BE-4C5A-B85D-8A638B687617

but so far have not seen any relevant info.
I guess it could be a bug in the RC.

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Sun 20 Aug 2017 06:30:04 PM UTC, comment #3: 

Sure, but I'd rather understand why the call isn't working the way it is.

In Java 9 I can construct an Integer with a double, and I can call compareTo with a double argument. I would like to know where Java 9 has changed something so that that is no longer possible. Particularly since Java 9 isn't actually released yet.

Mike Miller <mtmiller>
Project Administrator
Sun 20 Aug 2017 06:27:42 PM UTC, comment #2: 

Changing "assert(...)" call to:

assert (n.compareTo (int32(0)), 1)

makes it pass
(those are failing test in libinterp/octave-value/ov-java.cc-tst)

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Sun 20 Aug 2017 06:26:16 PM UTC, comment #1: 

I saw this also when trying to build with Java 9. Do you know where the relevant change in the Java 9 API is?

Mike Miller <mtmiller>
Project Administrator
Sun 20 Aug 2017 06:22:45 PM UTC, original submission:  

dev version compiled against java-9
(java-9-openjdk-9.0.0.181-1)

octave:1> n = javaObject ("java.lang.Integer", 1.35)
n =

<Java object: java.lang.Integer>

octave:2> assert (n.compareTo (0), 1)
error: [java] java.lang.ClassCastException: java.base/java.lang.Double cannot be cast to java.base/java.lang.Integer

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Digest:
   bug dependencies.

 

Carbon-Copy List
  • -email is unavailable- added by apjanke (Posted a comment)
  • -email is unavailable- added by mtmiller (Posted a comment)
  • -email is unavailable- added by dasergatskov (Submitted the item)
  •  

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only project members can vote.

     

     

     

    Follow 3 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2018-04-24 mtmiller Dependencies- => bugs #53728 is dependent
    2017-08-20 mtmiller Item GroupNone => Unexpected Error
        StatusNone => Need Info

    Back to the top


    Powered by Savane 3.5