Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

varargs and autoboxing causes segfault #509

Open
cmacdonald opened this issue Apr 12, 2020 · 4 comments
Open

varargs and autoboxing causes segfault #509

cmacdonald opened this issue Apr 12, 2020 · 4 comments

Comments

@cmacdonald
Copy link
Contributor

Arrays = autoclass("java.util.Arrays")
Collectors = autoclass("java.util.stream.Collectors")
#works fine
#words = Arrays.asList("1", "2")
#segfaults
numbers = Arrays.asList(1, 2)

Arrays.asList() uses varargs and a generic type

@cmacdonald
Copy link
Contributor Author

Here's the top of the stack according to the JVM dump:

V  [libjvm.dylib+0x3dd1e9]  jni_GetObjectClass+0xe3
C  [jnius.cpython-36m-darwin.so+0x42b3a]  __pyx_f_5jnius_lookup_java_object_name+0x1a
C  [jnius.cpython-36m-darwin.so+0x40b4c]  __pyx_f_5jnius_convert_jobject_to_python+0x7c
C  [jnius.cpython-36m-darwin.so+0x3fd2d]  __pyx_f_5jnius_convert_jarray_to_python+0xaed
C  [jnius.cpython-36m-darwin.so+0x34fcc]  __pyx_f_5jnius_release_args+0x3cc
C  [jnius.cpython-36m-darwin.so+0x4711a]  __pyx_pw_5jnius_10JavaMethod_9__call__+0xf2a
C  [python+0x9cc1]  _PyObject_FastCallDict+0xb1

This may imply that the call succeeded (release_args) is called in the finally block (https://github.com/kivy/pyjnius/blob/master/jnius/jnius_export_class.pxi#L786)

Why is the jarray converted back to Python? in case it has been updated?

Segfault must be at or the following line.

cdef jclass jcls = j_env[0].GetObjectClass(j_env, j_obj)

@mduczek
Copy link

mduczek commented Sep 28, 2020

also hitting this :/

@pPanda-beta
Copy link

This is still there with v1.3.0.

An easy and environment agnostic set of steps to reproduce :

docker run -it --rm agileops/centos-javapython:latest bash
pip3 install pyjnius==1.3.0
python3

And then run the following script

from jnius import autoclass
Arrays = autoclass('java.util.Arrays')
l = Arrays.asList(1, 2, 5)

Gives a nice core dump.

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f95ca97a8d9, pid=20, tid=0x00007f95cdbea740
#
# JRE version: OpenJDK Runtime Environment (8.0_171-b10) (build 1.8.0_171-b10)
# Java VM: OpenJDK 64-Bit Server VM (25.171-b10 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# V  [libjvm.so+0x6858d9]
#
# Core dump written. Default location: //core or core.20
#
# An error report file with more information is saved as:
# //hs_err_pid20.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#
Aborted (core dumped)

Solution?
Nothing yet, switch to JPype.

@Thrameos
Copy link

Thrameos commented Oct 8, 2020

A few notes for anyone who is trying this code under JPype.

JPype does handle this case though autoboxing without a casting operator, but may not be what you desire. The output of this autoconversion will be of type Number by contract as it has to refer to Python objects with a Python type int. Currently, the best match for this is java.lang.Long. In future releases, the exact type can be different (for example it may wish to use PyLong) as we try to better to actually store Python objects on Java objects rather than risk truncation.

>>> import jpype 
>>> jpype.startJVM()
>>> Arrays = jpype.JClass('java.util.Arrays')
>>> l = Arrays.asList(1,2,5)
>>> print(type(l[0]))
<java class 'java.lang.Long'>

In general if you want a specific type of boxing casting first is needed

l = Arrays.asList(JInt(1),JLong(2),JShort(5))

Note that in JPype varargs can auto unpack lists. The reason this works is that varargs in Java is implemented as Object[] so a Python list is checked to see if it can be unpacked to Object[]. If the elements all have defined Java conversions then the list unpacks into the varargs without error.

>>> l = Arrays.asList([jpype.JInt(i) for i in (1,2,5)])
>>> print(type(l[0]))
<java class 'java.lang.Integer'>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants