Title: Extending Thread and a java class/interface doesn't work
Type: behaviour Severity: normal
Components: Core Versions: Jython 2.7
Milestone: Jython 2.7.0
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: zyasoft Nosy List: amak, dtmGoogle, fwierzbicki, zyasoft
Priority: high Keywords: patch

Created on 2011-09-07.14:02:08 by dtmGoogle, last changed 2015-04-27.01:53:06 by zyasoft.

File name Uploaded Description Edit Remove
tinypyobjdiff.diff dtmGoogle, 2011-09-07.14:02:07
msg6641 (view) Author: Daniel Martin (dtmGoogle) Date: 2011-09-07.14:02:07
First, note that contains these two classes:

class JavaThread(object):
class Thread(JavaThread):

That is, "JavaThread" extends only python objects (although it contains a native java thread). Therefore, it should be possible to extend both Thread and a java interface, and then pass an instance of the resulting class to a java function accepting the interface.  However, if you try something like that after defining a single-method interface and a function that accepts an instance of that interface:

from com.invitemedia.jython import JythonTestMethods
from com.invitemedia.jython import StringInterface
from threading import Thread

class Foo(Thread, StringInterface):
  def stringMethod(self):
    return "yo yo yo"

a = JythonTestMethods()

print a.doStringInterfaceThing(Foo())

You end up with this error:

$ CLASSPATH=bin /opt/jython*/bin/jython ~/ 
Traceback (most recent call last):
  File "/home/dtm/", line 11, in <module>
    print a.doStringInterfaceThing(Foo())
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(
	at java.lang.reflect.Method.invoke(

java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: argument type mismatch

The issue is a combination of how threading.JavaThread overrides __tojava__ and how PyObjectDerived implements __tojava__.

JavaThread says:
    def __tojava__(self, c):
        if isinstance(self._thread, c):
            return self._thread
        if isinstance(self, c):
            return self
        return Py.NoConversion

PyObjectDerived says (in part, but this is the relevant part):
        PyType self_type=getType();
        PyObject impl=self_type.lookup("__tojava__");
        if (impl!=null)
            return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class);
        return super.__tojava__(c);

What happens is that JavaThread's __tojava__ method is first called with StringInterface; this hits the "return self" line, which then results in JavaThread's __tojava__ method being called with Java.lang.Object and hitting the "return self._thread" line. The end result is that PyObjectDerived's __tojava__ called with StringInterface.class returns an org.python.core.FunctionThread object.

I think that the best solution to this is to modify PyObjectDerived so that if  __call__ to the __tojava__ method returns *this*, we delegate to super.__tojava__(c). Patch attached.

With the patch applied, the script above works as it should.
msg6775 (view) Author: Frank Wierzbicki (fwierzbicki) Date: 2012-02-10.18:49:00
Hey Jim - I put you on this one since you have the most experience with our threading story. What do you think? If you think it looks good but don't have time to apply it I can double check it and apply. To me it looks like it might break backwards compatibility and so would be more of a 2.6/trunk thing. On the other hand it does fix a demonstrable bug.
msg7380 (view) Author: Frank Wierzbicki (fwierzbicki) Date: 2012-08-10.21:17:13
Ah I see now that this is not really a threading thing but an inheritance thing.
msg8703 (view) Author: Jim Baker (zyasoft) Date: 2014-06-19.04:50:21
Target beta 4, we got what appears to be a minimal and simple patch, we only need to add a test
msg9891 (view) Author: Jim Baker (zyasoft) Date: 2015-04-19.20:11:59
Fixed as of
Date User Action Args
2015-04-27 01:53:06zyasoftsetstatus: pending -> closed
2015-04-19 20:21:43zyasoftsetmilestone: Jython 2.7.1 -> Jython 2.7.0
2015-04-19 20:11:59zyasoftsetstatus: open -> pending
resolution: remind -> fixed
messages: + msg9891
versions: + Jython 2.7, - Jython 2.5
2015-04-15 20:44:07zyasoftsetmilestone: Jython 2.7.1
2014-09-26 04:52:30zyasoftsetassignee: fwierzbicki -> zyasoft
resolution: remind
2014-06-19 04:50:21zyasoftsetmessages: + msg8703
2013-02-25 18:20:49fwierzbickisetpriority: high
versions: + Jython 2.5, - 2.5.2
2012-08-10 21:17:14fwierzbickisetmessages: + msg7380
2012-08-10 17:25:07fwierzbickisetassignee: zyasoft -> fwierzbicki
2012-02-10 18:49:01fwierzbickisetassignee: zyasoft
messages: + msg6775
nosy: + fwierzbicki, zyasoft
2011-11-04 21:38:02amaksetnosy: + amak
2011-09-07 14:02:08dtmGooglecreate