王安安的记录 2024-02-22 16:03 采纳率: 20%
浏览 3
已结题

JNI(标签-Java|关键词-Cython)

Java通过JNI调用python文件出现错误:Java JNI调用的接口文件运行出错!

img


运行Java报错:

"D:\Program Files\Java\jdk17\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.2.2\lib\idea_rt.jar=55810:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.2.2\bin" -Dfile.encoding=UTF-8 -classpath D:\Users\AppData\IdeaProjects\demo_callpy\target\classes;D:\maven-jar\org\python\jython-standalone\2.7.0\jython-standalone-2.7.0.jar;D:\maven-jar\org\springframework\boot\spring-boot-starter-web\3.0.2\spring-boot-starter-web-3.0.2.jar;D:\maven-jar\org\springframework\boot\spring-boot-starter-json\3.0.2\spring-boot-starter-json-3.0.2.jar;D:\maven-jar\com\fasterxml\jackson\core\jackson-databind\2.14.1\jackson-databind-2.14.1.jar;D:\maven-jar\com\fasterxml\jackson\core\jackson-annotations\2.14.1\jackson-annotations-2.14.1.jar;D:\maven-jar\com\fasterxml\jackson\core\jackson-core\2.14.1\jackson-core-2.14.1.jar;D:\maven-jar\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.14.1\jackson-datatype-jdk8-2.14.1.jar;D:\maven-jar\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.14.1\jackson-datatype-jsr310-2.14.1.jar;D:\maven-jar\com\fasterxml\jackson\module\jackson-module-parameter-names\2.14.1\jackson-module-parameter-names-2.14.1.jar;D:\maven-jar\org\springframework\boot\spring-boot-starter-tomcat\3.0.2\spring-boot-starter-tomcat-3.0.2.jar;D:\maven-jar\org\apache\tomcat\embed\tomcat-embed-core\10.1.5\tomcat-embed-core-10.1.5.jar;D:\maven-jar\org\apache\tomcat\embed\tomcat-embed-el\10.1.5\tomcat-embed-el-10.1.5.jar;D:\maven-jar\org\apache\tomcat\embed\tomcat-embed-websocket\10.1.5\tomcat-embed-websocket-10.1.5.jar;D:\maven-jar\org\springframework\spring-web\6.0.4\spring-web-6.0.4.jar;D:\maven-jar\org\springframework\spring-beans\6.0.4\spring-beans-6.0.4.jar;D:\maven-jar\io\micrometer\micrometer-observation\1.10.3\micrometer-observation-1.10.3.jar;D:\maven-jar\io\micrometer\micrometer-commons\1.10.3\micrometer-commons-1.10.3.jar;D:\maven-jar\org\springframework\spring-webmvc\6.0.4\spring-webmvc-6.0.4.jar;D:\maven-jar\org\springframework\spring-aop\6.0.4\spring-aop-6.0.4.jar;D:\maven-jar\org\springframework\spring-context\6.0.4\spring-context-6.0.4.jar;D:\maven-jar\org\springframework\spring-expression\6.0.4\spring-expression-6.0.4.jar;D:\maven-jar\org\springframework\boot\spring-boot-starter\3.0.2\spring-boot-starter-3.0.2.jar;D:\maven-jar\org\springframework\boot\spring-boot\3.0.2\spring-boot-3.0.2.jar;D:\maven-jar\org\springframework\boot\spring-boot-autoconfigure\3.0.2\spring-boot-autoconfigure-3.0.2.jar;D:\maven-jar\org\springframework\boot\spring-boot-starter-logging\3.0.2\spring-boot-starter-logging-3.0.2.jar;D:\maven-jar\ch\qos\logback\logback-classic\1.4.5\logback-classic-1.4.5.jar;D:\maven-jar\ch\qos\logback\logback-core\1.4.5\logback-core-1.4.5.jar;D:\maven-jar\org\apache\logging\log4j\log4j-to-slf4j\2.19.0\log4j-to-slf4j-2.19.0.jar;D:\maven-jar\org\apache\logging\log4j\log4j-api\2.19.0\log4j-api-2.19.0.jar;D:\maven-jar\org\slf4j\jul-to-slf4j\2.0.6\jul-to-slf4j-2.0.6.jar;D:\maven-jar\jakarta\annotation\jakarta.annotation-api\2.1.1\jakarta.annotation-api-2.1.1.jar;D:\maven-jar\org\springframework\spring-core\6.0.4\spring-core-6.0.4.jar;D:\maven-jar\org\springframework\spring-jcl\6.0.4\spring-jcl-6.0.4.jar;D:\maven-jar\org\yaml\snakeyaml\1.33\snakeyaml-1.33.jar;D:\maven-jar\org\springframework\boot\spring-boot-devtools\3.0.2\spring-boot-devtools-3.0.2.jar;D:\maven-jar\org\slf4j\slf4j-api\2.0.6\slf4j-api-2.0.6.jar com.example.demo.JNITest.Demo
Exception in thread "main" java.lang.UnsatisfiedLinkError: 'void com.example.demo.JNITest.Test.initModule()'
    at com.example.demo.JNITest.Test.initModule(Native Method)
    at com.example.demo.JNITest.Demo.main(Demo.java:16)

pycharm里面的结构:

img

img


先对pyx文件:
cythonize -i -3 JavaTest.pyx可以正常运行
python setup.py build_ext --inplace无报错

这个是setup.py文件

```python

from distutils.extension import Extension
from distutils.core import setup
from Cython.Build import cythonize
sourcefiles = ['Test.pyx', r'D:\Users\wangxiaofei\MYPYCHARM\JniPy\main.c']

extensions = [Extension("libTest", sourcefiles,
                        include_dirs=[r'D:\Program Files\Java\jdk17\include',
                                      r'D:\Program Files\Java\jdk17\include\win32'
                                      r'D:\Users\Python39\include',
                                      ],
                        library_dirs=[r'D:\Users\Python39\Lib'],
                        libraries=['python39'])]
setup(
    ext_modules = cythonize("Test.pyx")
)

这个是Test.py:
 FileName: Test.pyx
# 示例代码:将输入的字符串转变为大写
def logic(param):
    print('this is a logic function')
    print('param is [%s]' % param)
    return param.upper()


# 接口函数,导出给Java Native的接口
def JNI_API_TestFunction(param):
    print("enter JNI_API_test_function")
    result = logic(param)
    print("leave JNI_API_test_function")
    return result



这个是main.c:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <Python.h>
#include <stdio.h>

#ifndef _Included_main
#define _Included_main
#ifdef __cplusplus
extern"C" {
#endif

#if PY_MAJOR_VERSION < 3
# define MODINIT(name)  init ## name
#else
# define MODINIT(name)  PyInit_ ## name
#endif
PyMODINIT_FUNC  MODINIT(Test)(void);

JNIEXPORT void JNICALL Java_Test_initModule
(JNIEnv *env, jobject obj) {
  PyImport_AppendInittab("Test", MODINIT(Test));
  Py_Initialize();

  PyRun_SimpleString("import os");
  PyRun_SimpleString("__name__ = \"__main__\"");
  PyRun_SimpleString("import sys");
  PyRun_SimpleString("sys.path.append('./')");

  PyObject* m = PyInit_Test_Test();
  if (!PyModule_Check(m)) {
      PyModuleDef *mdef = (PyModuleDef *) m;
      PyObject *modname = PyUnicode_FromString("__main__");
      m = NULL;
      if (modname) {
        m = PyModule_NewObject(modname);
        Py_DECREF(modname);
        if (m) PyModule_ExecDef(m, mdef);
      }
  }
  PyEval_InitThreads();
}


JNIEXPORT void JNICALL Java_Test_uninitModule
(JNIEnv *env, jobject obj) {
  Py_Finalize();
}

JNIEXPORT jstring JNICALL Java_Test_testFunction
(JNIEnv *env, jobject obj, jstring string)
{
  constchar* param = (char*)(*env)->GetStringUTFChars(env, string, NULL);
  static PyObject *s_pmodule = NULL;
  static PyObject *s_pfunc = NULL;
  if (!s_pmodule || !s_pfunc) {
    s_pmodule = PyImport_ImportModule("Test");
    s_pfunc = PyObject_GetAttrString(s_pmodule, "JNI_API_testFunction");
  }
  PyObject *pyRet = PyObject_CallFunction(s_pfunc, "s", param);
  (*env)->ReleaseStringUTFChars(env, string, param);
  if (pyRet) {
    jstring retJstring = (*env)->NewStringUTF(env, PyUnicode_AsUTF8(pyRet));
    Py_DECREF(pyRet);
    return retJstring;
  } else {
    PyErr_Print();
    return (*env)->NewStringUTF(env, "error");
  }
}
#ifdef __cplusplus
}
#endif
#endif

这个是Test.java:

```java
package com.example.demo.JNITest;

// FileName: Test.java
public class Test {
    public native void initModule();

    public native void uninitModule();

    public native String testFunction(String param);
}



```c

public class Demo {
        static
        {




                System.load("D:\\Users\\wangxiaofei\\MYPYCHARM\\JniPy\\Test.cp39-win_amd64.pyd");
        }
public static void main(String[] args) {


        Test tester = new Test();
        tester.initModule();
        String result = tester.testFunction("this is called from java");
        tester.uninitModule();

        System.out.println(result);
        }
        }

  • 写回答

1条回答 默认 最新

  • GISer Liu 2024-02-22 16:04
    关注

    该回答引用自GPT-3.5,由博主GISer Liu编写:

    根据你提供的信息,出现 java.lang.UnsatisfiedLinkError 错误通常是由于 JNI 找不到或无法加载指定的本地库导致的。根据你的描述,你在 Java 中通过 JNI 调用 Python 文件,但是出现了这个错误。

    错误信息中显示的是 java.lang.UnsatisfiedLinkError: 'void com.example.demo.JNITest.Test.initModule()',这表明 JNI 无法找到 initModule 方法的本地实现。这可能是因为在加载本地库时出现了问题。

    以下是解决问题的思路和方案:

    1. 检查本地库加载路径
      确保 Java 在加载本地库时可以找到正确的路径。你在 Java 代码中使用了 System.load("D:\\Users\\wangxiaofei\\MYPYCHARM\\JniPy\\Test.cp39-win_amd64.pyd") 来加载本地库,确保这个路径是正确的。如果本地库的路径有误,就会导致 UnsatisfiedLinkError 错误。

    2. 检查本地库的构建和链接
      确保 Python 模块被正确地构建成本地库,并且与 Java 代码中加载的路径一致。你在 Python 中使用了 Cython 来构建 Python 模块,通过 cythonize 命令和 setup.py 文件来实现。在 setup.py 文件中,确保 sourcefiles 变量中包含了正确的文件,并且相关的路径配置正确。

    3. 确保本地库中包含了正确的函数实现
      在你的 C 代码中,确保实现了正确的 JNI 函数。特别是,在 Java_Test_initModule 方法中,你需要通过 PyImport_AppendInittab 来注册 Python 模块,并且确保 PyInit_Test_Test 调用返回了正确的模块对象。检查这部分代码是否正确地构建了 Python 模块的本地实现。

    4. 检查 Java Native 方法的命名
      确保 Java Native 方法的命名与 C 代码中实现的 JNI 函数名称一致。在你的 Java 代码中,initModuleuninitModuletestFunction 这些方法对应了 C 代码中的 JNI 函数,确保这些方法名没有拼写错误并且与 C 代码中的函数名一致。

    5. 调试与日志记录
      如果以上步骤都没有解决问题,可以尝试在代码中添加日志记录,以便排查问题。在 C 代码中可以使用 printf 输出日志信息,查看本地库加载和函数调用的情况。同时,在 Java 中也可以添加日志记录,查看本地库加载情况以及 JNI 方法的调用情况。

    根据这些思路和方案,你可以逐步排查问题,并找到解决方法。希望能帮到你解决这个 JNI 调用 Python 的问题!

    如果该回答解决了您的问题,请采纳!如果没有,请参考以下方案进行修订

    用户答题指南

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 3月2日
  • 已采纳回答 2月23日
  • 创建了问题 2月22日

悬赏问题

  • ¥15 Coze智能助手搭建过程中的问题请教
  • ¥15 12864只亮屏 不显示汉字
  • ¥20 三极管1000倍放大电路
  • ¥15 vscode报错如何解决
  • ¥15 前端vue CryptoJS Aes CBC加密后端java解密
  • ¥15 python随机森林对两个excel表格读取,shap报错
  • ¥15 基于STM32心率血氧监测(OLED显示)相关代码运行成功后烧录成功OLED显示屏不显示的原因是什么
  • ¥100 X轴为分离变量(因子变量),如何控制X轴每个分类变量的长度。
  • ¥30 求给定范围的全体素数p的(p-2)/p的连乘积值
  • ¥15 VFP如何使用阿里TTS实现文字转语音?