jpype-project / jpype

JPype is cross language bridge to allow Python programs full access to Java class libraries.
http://www.jpype.org
Other
1.07k stars 176 forks source link

PyPy3 support #440

Open Thrameos opened 5 years ago

Thrameos commented 5 years ago

This has been requested in the past #146, and we are very close. Though a top level goal of the core rewrite, our efforts to replace the Python wrapper solved almost all the issue we were having with PyPy. There was some code in the _jpype core that was treating Tuples as sequences in ways that PyPy did not accept. Those all got fixed so 98% of everything is working.

Now as the last 2%. So two things need to happen here.

The memory management is the harder of the issue. We need to lock step the garbage collection of the two machines. If Java runs out of memory it need to pulse PyPy to run a GC so that we don't end up out of memory. The same is true in reverse. If PyPy resources are being held by Java and it just hasn't collected it yet, then Java needs a forced GC. We have the pattern to force a GC on Java so we can link one way. We don't have a pattern for the other.

It is likely usable in the current state with the caveat of the one bug and the memory issue. But we should shoot for better. I am targeting this for 0.8 but will likely slide to sometime in 0.7 series.

PyPy 2 is another story. PyPy 2 has certain restrictions on deriving from based types like bool and int. We extended them to make conversions without a forced call to boolValue. We can make the base class change in PyPy which will still work, but we will end up with a different conversion rule set requiring more casting. This means disabling all the tests for that conversion type. Still doable, but not unless some user really need wants it as maintaining a test bench for a version that no one is using is not worth it.

Thrameos commented 5 years ago

Ran the test bench on Ubuntu Xenial and everything passed (except broken memory test) without issues. No idea why char conversions would fail on the CI.

micmn commented 4 years ago

PyPy 2 is another story. PyPy 2 has certain restrictions on deriving from based types like bool and int. We extended them to make conversions without a forced call to boolValue. We can make the base class change in PyPy which will still work, but we will end up with a different conversion rule set requiring more casting. This means disabling all the tests for that conversion type. Still doable, but not unless some user really need wants it as maintaining a test bench for a version that no one is using is not worth it.

I'm investigating using jpype to call java code from robot acceptance tests framework. I understand that it would be possible to run jpype under PyPy 2 but I'm not able to evaluate the effort required and what changes are needed on jpype. Could you give me some pointers on that? Thanks.

Thrameos commented 4 years ago

I currently do not have any plans to support PyPy2 as it has a very challenging object model relative to Python 2.7 and Python 3.

If you would like to get it work you would need to remove the specializations of Boxed types with primitives. Prior to Python 2.7 I believe it was not possible to add dictionaries to extensions of int, long, or float. Thus the problem with the current API. If you remove the type from the declaration line then it would likely work. Ie class JBoxedInteger(int, object): would need to become JBoxedInteger(object): . This will break a number of tests regarding boxed types.

Pretty much just build it, try to run it and the error messages should point you to the classes with the problematic cases. Most of the really bad problems (Ie using the Sequence API on a Tuple, which PyPy didn't implement properly have been addressed, so all problems should be in the Python code.

The secondary problem with PyPy is linking of the garbage collectors. When using JPype with normal reference counting the aggressive counting of Python keeps it from building up too many objects. In PyPy the garbage collector allows small objects to live on even when they point to large Java objects. Thus you can get a case where Java runs out of memory. In principle, you can detect when Java is requesting a GC and then call the PyPy one to force it to give up the unneeded Java objects. But I could never find an API hook to make that happen.

I am in the process of dropping support for Python 2 as of the next major version as the object model of Python is really holding things back in terms of performance. But if you don't mind building a modified version for your uses it should work.

Thrameos commented 4 years ago

This one remains illusive. We can compile under Pypy3 easy enough, but something fails immediately in the type system. And I have no clue how to debug it. Thus this is going to be pushed to 0.9.