Issue2104

classification
Title: Jython can break Java polymorphism
Type: Severity: normal
Components: Core Versions: Jython 2.7
Milestone:
process
Status: closed Resolution: works for me
Dependencies: Superseder:
Assigned To: Nosy List: babelmania, jsaiz, zyasoft
Priority: high Keywords:

Created on 2013-11-28.10:42:48 by jsaiz, last changed 2015-04-27.01:53:26 by zyasoft.

Messages
msg8181 (view) Author: Jaime (jsaiz) Date: 2013-11-28.10:42:47
Consider a Java hierarchy like this:

public interface Copyable {
    Copyable copy();
}

public class CopyableBase implements Copyable {
    @Override public CopyableBase copy() {
        return new CopyableBase();
    }
}

public class CopyableParent extends CopyableBase {
    @Override public CopyableParent copy() {
        return new CopyableParent();
    }
}

public class CopyableChild extends CopyableParent {
    @Override public CopyableChild copy() {
        return new CopyableChild();
    }
}

If you execute this code in Jython:

cc = CopyableChild()
copy = cc.copy()

the PyReflectedFunction object to call the copy() method is built with the CopyableParent's version of copy(), not with the CopyableChild's version, which should be preferred as it overrides the parent's one.

This does not cause any trouble in the vast majority of the cases, even in this example: java.lang.reflect.Method.invoke() repairs it by calling the child's version, even if the parent's one is asked to be executed.

However, in a specific case of a much more complex hierarchy, Jython keeps choosing the wrong method, but Method.invoke() is not able to repair it for some reason, and the parent's method is called, thus breaking Java polymorphism.

It can be fixed by commenting out the following lines of org.python.core.ReflectedArgs.compareTo:

        // For static methods, use the child's version
        // For instance methods, use the parent's version
        if (!this.isStatic) {
            replace = !replace;
        }

Patching jython.jar by skipping this "if" solves the issue in our project; however it should be ammended in future Jython versions too.
msg8182 (view) Author: Jaime (jsaiz) Date: 2013-11-28.10:47:06
I forgot to mention that I'm using:

* Java 1.7.0_45
* Jython 2.5.2
* Linux Red Hat 6
msg8256 (view) Author: Jorgo Bakker (babelmania) Date: 2014-03-19.12:48:14
Can we up the priority of this, as it is rather annoying and the fix seems to be easy enough.
msg9101 (view) Author: Jim Baker (zyasoft) Date: 2014-10-06.03:39:44
Time to look at the suggested change given how minor it is

Target beta 4
msg9183 (view) Author: Jorgo Bakker (babelmania) Date: 2014-10-29.16:47:25
Very much appreciated!
msg9876 (view) Author: Jim Baker (zyasoft) Date: 2015-04-17.05:02:43
Due to recent super fixes for #1540, I reinvestigated this bug. However, I cannot reproduce the problem. Interestingly removing the problematic code for Jaime does nothing in the regrtest, nor in an additional test that I added to investigate further.

So please consider this an opportunity to propose a patch to HierarchyTest to demonstrate the more complex hierarchy that does show this problem. Thanks!

Please see what I did to support some additional testing in this new changeset, https://hg.python.org/jython/rev/1c420dee2a19
msg9890 (view) Author: Jim Baker (zyasoft) Date: 2015-04-19.19:15:02
It's quite possible we fixed this in 2.7, however we would not backport to 2.5. Closing out accordingly.
History
Date User Action Args
2015-04-27 01:53:26zyasoftsetstatus: pending -> closed
2015-04-19 19:15:02zyasoftsetstatus: open -> pending
messages: + msg9890
versions: - Jython 2.5
2015-04-17 05:02:44zyasoftsetresolution: works for me
messages: + msg9876
2014-10-29 16:47:25babelmaniasetmessages: + msg9183
2014-10-06 03:39:44zyasoftsetpriority: high
messages: + msg9101
2014-05-04 20:05:19zyasoftsetnosy: + zyasoft
2014-03-19 12:48:14babelmaniasetnosy: + babelmania
messages: + msg8256
2013-11-28 10:47:06jsaizsetmessages: + msg8182
2013-11-28 10:42:48jsaizcreate