Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hanslovsky/69ab3d007c09749ce400b678829eea18 to your computer and use it in GitHub Desktop.
Save hanslovsky/69ab3d007c09749ce400b678829eea18 to your computer and use it in GitHub Desktop.
Minimal failing example for PyJNIus on windows
- Install conda
- Install PyJNIus dependencies through conda and/or pip
- Install OpenJDK `1.8.0_131`
- install Apache ant
- install visual cpp build tools
- Instead of make run commands in Makefile by hand
- `ant all`
- `python setup.py build_ext --inplace -f`
- for tests:
- `cd tests`
- `set CLASSPATH=..\build\test-classes;..\build\classes`
- `set PYTHONPATH=..`
- `nosetests -v > nosetests.log 2>&1` (compare nosetests.log in this gist)
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007fff4a2adff4, pid=10772, tid=0x0000000000000ff4
#
# JRE version: Java(TM) SE Runtime Environment (8.0_131-b11) (build 1.8.0_131-b11)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C [jnius.cp36-win_amd64.pyd+0x1dff4]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\Zottel\hs_err_pid10772.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
# See fail.log for error message
import jnius_config
jnius_config.add_classpath(r'C:\Users\Zottel\git\pyjnius\build\pyjnius.jar')
from jnius import PythonJavaClass, java_method, autoclass
class AddOne( PythonJavaClass ):
__javainterfaces__ = ['java/util/function/IntUnaryOperator']
def __init__(self):
super( AddOne, self ).__init__()
@java_method('(I)I')
def applyAsInt( self, operand ):
return operand + 1
stream = autoclass('java.util.stream.IntStream').range( 0, 10 )
ao = AddOne()
stream.map( ao ).toArray()
test_assignable (test_assignable.AssignableFrom) ... ok
test_class_not_found (test_bad_declaration.BadDeclarationTest) ... ok
test_invalid_attribute (test_bad_declaration.BadDeclarationTest) ... ok
test_invalid_static_call (test_bad_declaration.BadDeclarationTest) ... ok
test_java_exception_chaining (test_bad_declaration.BadDeclarationTest) ... ok
test_java_exception_handling (test_bad_declaration.BadDeclarationTest) ... ok
test_with_too_much_arguments (test_bad_declaration.BadDeclarationTest) ... ok
test_instance_fields (test_basics.BasicsTest) ... ok
test_instance_methods (test_basics.BasicsTest) ... ok
test_instance_set_fields (test_basics.BasicsTest) ... ok
test_instances_methods_array (test_basics.BasicsTest) ... ok
test_instances_methods_params (test_basics.BasicsTest) ... ok
test_instances_methods_params_array_byte (test_basics.BasicsTest) ... ok
test_instances_methods_params_object_list_float (test_basics.BasicsTest) ... ok
test_instances_methods_params_object_list_int (test_basics.BasicsTest) ... ok
test_instances_methods_params_object_list_long (test_basics.BasicsTest) ... ok
test_instances_methods_params_object_list_str (test_basics.BasicsTest) ... ok
test_return_array_as_object_array_of_strings (test_basics.BasicsTest) ... ok
test_return_array_as_object_of_integers (test_basics.BasicsTest) ... ok
test_static_fields (test_basics.BasicsTest) ... ok
test_static_methods (test_basics.BasicsTest) ... ok
test_bytearray_ascii (test_bytearray.StringArgumentForByteArrayTest) ... ok
test_create_bytearray (test_bytearray.StringArgumentForByteArrayTest) ... ok
test_fill_byte_array (test_bytearray.StringArgumentForByteArrayTest) ... ok
test_string_arg_for_byte_array (test_bytearray.StringArgumentForByteArrayTest) ... ok
test_string_arg_with_signed_char (test_bytearray.StringArgumentForByteArrayTest) ... ok
test_multiple_constructors (test_cast.MultipleSignatureTest) ... ok
test_static_methods (test_class_argument.BasicsTest) ... ok
test_enum (test_enum.SimpleEnum) ... ok
test_value (test_enum.SimpleEnum) ... ok
test_printf (test_implementation.ImplementationTest) ... hi
hi jnius other string
ok
test_println (test_implementation.ImplementationTest) ...
ok
test_unicode (test_implementation.ImplementationTest) ... éok
test_reflect_enum_in_interface (test_interface.Interface) ... ok
test_reflect_interface (test_interface.Interface) ... ok
test_multiple_constructors (test_method_multiple_signatures.MultipleSignature) ... ok
test_multiple_methods (test_method_multiple_signatures.MultipleSignature) ... ok
test_multiple_methods_no_args (test_method_multiple_signatures.MultipleSignature) ... ok
test_multiple_methods_one_arg (test_method_multiple_signatures.MultipleSignature) ... ok
test_multiple_methods_two_args (test_method_multiple_signatures.MultipleSignature) ... ok
test_multiple_methods_two_args_and_varargs (test_method_multiple_signatures.MultipleSignature) ... ok
test_multiple_methods_two_string_and_an_integer (test_method_multiple_signatures.MultipleSignature) ... ok
test_multiple_methods_two_string_and_two_integers (test_method_multiple_signatures.MultipleSignature) ... ok
test_multiple_methods_varargs (test_method_multiple_signatures.MultipleSignature) ... ok
test_multiple_dimensions (test_multidimension.MultipleDimensionsTest) ... ok
test_string_output_args (test_output_args.OutputArgs) ...
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007fff4facdff4, pid=13156, tid=0x0000000000002f84
#
# JRE version: Java(TM) SE Runtime Environment (8.0_131-b11) (build 1.8.0_131-b11)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C [jnius.cp36-win_amd64.pyd+0x1dff4]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\Zottel\Downloads\pyjnius-master\pyjnius-master\tests\hs_err_pid13156.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

I assume now that these lines in jnius/jnius_proxy.pxi and these lines cause the issue:

cdef jobject py_invoke0(JNIEnv *j_env, jobject j_this, jobject j_proxy, jobject
        j_method, jobjectArray args) except * with gil:

    from .reflect import get_signature, Method
    cdef jfieldID ptrField
    cdef jlong jptr
    cdef object py_obj
    cdef JavaClass method
    cdef jobject j_arg

    # get the python object
    ptrField = j_env[0].GetFieldID(j_env,
        j_env[0].GetObjectClass(j_env, j_this), "ptr", "J")
    jptr = j_env[0].GetLongField(j_env, j_this, ptrField)
    py_obj = <object><void *>jptr

    # extract the method information
    method = Method(noinstance=True)
    method.instanciate_from(create_local_ref(j_env, j_method))
    ret_signature = get_signature(method.getReturnType())
    args_signature = [get_signature(x) for x in method.getParameterTypes()]

    # convert java argument to python object
    # native java type are given with java.lang.*, even if the signature say
    # it's a native type.
    py_args = []
    convert_signature = {
        'Z': 'Ljava/lang/Boolean;',
        'B': 'Ljava/lang/Byte;',
        'C': 'Ljava/lang/Character;',
        'S': 'Ljava/lang/Short;',
        'I': 'Ljava/lang/Integer;',
        'J': 'Ljava/lang/Long;',
        'F': 'Ljava/lang/Float;',
        'D': 'Ljava/lang/Double;'}

    for index, arg_signature in enumerate(args_signature):
        arg_signature = convert_signature.get(arg_signature, arg_signature)
        j_arg = j_env[0].GetObjectArrayElement(j_env, args, index)
        py_arg = convert_jobject_to_python(j_env, arg_signature, j_arg)
        j_env[0].DeleteLocalRef(j_env, j_arg)
        py_args.append(py_arg)

    # really invoke the python method
    name = method.getName()
    ret = py_obj.invoke(method, *py_args)

    # convert back to the return type
    # use the populate_args(), but in the reverse way :)
    t = ret_signature[:1]

    # did python returned a "native" type ?
    jtype = None

    if ret_signature == 'Ljava/lang/Object;':
        # generic object, try to manually convert it
        tp = type(ret)
        if tp == int:
            jtype = 'J'
        elif tp == float:
            jtype = 'D'
        elif tp == bool:
            jtype = 'Z'
    elif len(ret_signature) == 1:
        jtype = ret_signature

    try:
        return convert_python_to_jobject(j_env, jtype or ret_signature, ret)
    except Exception as e:
        traceback.print_exc(e)


cdef jobject invoke0(JNIEnv *j_env, jobject j_this, jobject j_proxy, jobject
        j_method, jobjectArray args) with gil:
    try:
        return py_invoke0(j_env, j_this, j_proxy, j_method, args)
    except Exception as e:
        traceback.print_exc(e)
        return NULL
cdef jobject convert_python_to_jobject(JNIEnv *j_env, definition, obj) except *:
    cdef jobject retobject, retsubobject
    cdef jclass retclass
    cdef jmethodID redmidinit
    cdef jvalue j_ret[1]
    cdef JavaClass jc
    cdef JavaObject jo
    cdef JavaClassStorage jcs
    cdef PythonJavaClass pc
    cdef int index

    if definition[0] == 'V':
        return NULL
    elif definition[0] == 'L':
        if obj is None:
            return NULL
        elif isinstance(obj, basestring) and jstringy_arg(definition):
            return j_env[0].NewStringUTF(j_env, <char *><bytes>obj)
        elif isinstance(obj, str) and PY_MAJOR_VERSION >= 3 and jstringy_arg(definition):
            utf8 = obj.encode('utf-8')
            return j_env[0].NewStringUTF(j_env, <char *><bytes>utf8)
        elif isinstance(obj, (int, long)) and \
                definition in (
                    'Ljava/lang/Integer;',
                    'Ljava/lang/Number;',
                    'Ljava/lang/Long;',
                    'Ljava/lang/Object;'):
            j_ret[0].i = obj
            retclass = j_env[0].FindClass(j_env, 'java/lang/Integer')
            retmidinit = j_env[0].GetMethodID(j_env, retclass, '<init>', '(I)V')
            retobject = j_env[0].NewObjectA(j_env, retclass, retmidinit, j_ret)
            return retobject
        elif isinstance(obj, type):
            jc = obj
            return jc.j_cls
        elif isinstance(obj, JavaClass):
            jc = obj
            check_assignable_from(j_env, jc, definition[1:-1])
            return jc.j_self.obj
        elif isinstance(obj, JavaObject):
            jo = obj
            return jo.obj
        elif isinstance(obj, MetaJavaClass):
            jcs = obj.__cls_storage
            return jcs.j_cls
        elif isinstance(obj, PythonJavaClass):
            # from python class, get the proxy/python class
            pc = obj
            # get the java class
            jc = pc.j_self
            # get the localref
            return jc.j_self.obj
        elif isinstance(obj, (tuple, list)):
            return convert_pyarray_to_java(j_env, definition, obj)
        else:
            raise JavaException('Invalid python object for this '
                    'argument. Want {0!r}, got {1!r}'.format(
                        definition[1:-1], obj))

    elif definition[0] == '[':
        if PY_MAJOR_VERSION < 3:
            conversions = {
                int: 'I',
                bool: 'Z',
                long: 'J',
                float: 'F',
                basestring: 'Ljava/lang/String;',
            }
        else:
            conversions = {
                int: 'I',
                bool: 'Z',
                long: 'J',
                float: 'F',
                str: 'Ljava/lang/String;',
                bytes: 'B'
            }
        retclass = j_env[0].FindClass(j_env, 'java/lang/Object')
        retobject = j_env[0].NewObjectArray(j_env, len(obj), retclass, NULL)
        for index, item in enumerate(obj):
            item_definition = conversions.get(type(item), definition[1:])
            retsubobject = convert_python_to_jobject(
                    j_env, item_definition, item)
            j_env[0].SetObjectArrayElement(j_env, retobject, index,
                    retsubobject)
        return retobject

    elif definition == 'B':
        retclass = j_env[0].FindClass(j_env, 'java/lang/Byte')
        retmidinit = j_env[0].GetMethodID(j_env, retclass, '<init>', '(B)V')
        j_ret[0].b = obj
    elif definition == 'S':
        retclass = j_env[0].FindClass(j_env, 'java/lang/Short')
        retmidinit = j_env[0].GetMethodID(j_env, retclass, '<init>', '(S)V')
        j_ret[0].s = obj
    elif definition == 'I':
        retclass = j_env[0].FindClass(j_env, 'java/lang/Integer')
        retmidinit = j_env[0].GetMethodID(j_env, retclass, '<init>', '(I)V')
        j_ret[0].i = int(obj)
    elif definition == 'J':
        retclass = j_env[0].FindClass(j_env, 'java/lang/Long')
        retmidinit = j_env[0].GetMethodID(j_env, retclass, '<init>', '(J)V')
        j_ret[0].j = obj
    elif definition == 'F':
        retclass = j_env[0].FindClass(j_env, 'java/lang/Float')
        retmidinit = j_env[0].GetMethodID(j_env, retclass, '<init>', '(F)V')
        j_ret[0].f = obj
    elif definition == 'D':
        retclass = j_env[0].FindClass(j_env, 'java/lang/Double')
        retmidinit = j_env[0].GetMethodID(j_env, retclass, '<init>', '(D)V')
        j_ret[0].d = obj
    elif definition == 'C':
        retclass = j_env[0].FindClass(j_env, 'java/lang/Char')
        retmidinit = j_env[0].GetMethodID(j_env, retclass, '<init>', '(C)V')
        j_ret[0].c = ord(obj)
    elif definition == 'Z':
        retclass = j_env[0].FindClass(j_env, 'java/lang/Boolean')
        retmidinit = j_env[0].GetMethodID(j_env, retclass, '<init>', '(Z)V')
        j_ret[0].z = 1 if obj else 0
    else:
        assert(0)

    assert(retclass != NULL)
    # XXX do we need a globalref or something ?
    retobject = j_env[0].NewObjectA(j_env, retclass, retmidinit, j_ret)
    return retobject
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment