我使用Python和Py4J来测试JNI代码。但是,当我调用JNI代码时,会得到以下错误:
py4j.protocol.Py4JJavaError: An error occurred while calling o37.createInstance.
: java.lang.UnsatisfiedLinkError: com.mgr_api_JNI.createInstance(Lcom/mgr_api_types$EDisplayType;Ljava/lang/String;Lcom/mgr_api_types$ECommType;Ljava/lang/String;)V
at com.mgr_api_JNI.createInstance(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244)
at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357)
at py4j.Gateway.invoke(Gateway.java:282)
at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
at py4j.commands.CallCommand.execute(CallCommand.java:79)
at py4j.GatewayConnection.run(GatewayConnection.java:238)
at java.base/java.lang.Thread.run(Thread.java:834)
link 1
,
link 2
link 3
,
link 4
,
link 5
,和
link 6
,再加上其他的,但没有一个能解决我的问题。
代码
api_JNI.java经理:
package com;
import com.mgr_api_types.*;
public class mgr_api_JNI
{
static
{
try
{
System.loadLibrary("Mngr"); // Use "-Djava.library.path=[path to library]" option to load this library
}
catch (UnsatisfiedLinkError e)
{
System.err.println("Native code library 'Mngr' failed to load.\n" + e);
}
}
public native void createInstance(com.mgr_api_types.EDisplayType displayType,
String displaySerialNumber,
com.mgr_api_types.ECommType commType,
String portName);
}
import com.*;
import py4j.GatewayServer;
public class testsJNI
{
public static void main(String args[])
{
testsJNI testApp = new testsJNI();
// Py4J server
GatewayServer server = new GatewayServer(testApp);
server.turnLoggingOff();
server.start();
}
}
com_mgr_api_JNI.h公司
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_mgr_api_JNI */
#ifndef _Included_com_mgr_api_JNI
#define _Included_com_mgr_api_JNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_mgr_api_JNI
* Method: createInstance
* Signature: (Lcom/mgr_api_types/EDisplayType;Ljava/lang/String;Lcom/mgr_api_types/ECommType;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_mgr_1api_1JNI_createInstance
(JNIEnv *, jobject, jobject, jstring, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
com_mgr_api_JNI.cpp公司:
#include "com_mgr_api_JNI.h"
static manager::CManagerApi* manager = NULL;
JNIEXPORT void JNICALL Java_com_mgr_1api_1JNI_createInstance(
JNIEnv *env,
jobject thisObj,
jobject displayType,
jstring displaySerialNumber,
jobject commType,
jstring portName)
{
manager::EDisplayType dType = convertObjectToDisplayType(env, displayType);
const char* serialNumber = env->GetStringUTFChars(displaySerialNumber, 0);
manager::ECommType comm = convertObjectToCommType(env, commType);
const char* port = env->GetStringUTFChars(portName, 0);
char buf[100];
sprintf(buf,"%s",port);
std::string portStr = buf;
sprintf(buf,"%s",serialNumber);
std::string serialNumStr = buf;
if (manager == NULL)
{
manager = manager::CManagerApi::get();
manager->initialize(dType, serialNumStr, comm, portStr);
}
// Release memory
env->ReleaseStringUTFChars(displaySerialNumber, serialNumber);
env->ReleaseStringUTFChars(portName, port);
}
Java代码的命令行执行:
java -cp /mnt/c/Workspace/library/java/:.:/home/fred/.local/share/py4j/py4j0.10.7.jar -Djava.library.path=/mnt/c/Workspace/build/library/ testsJNI
做一个
-XshowSettings:properties
显示以下属性:
awt.toolkit = sun.awt.X11.XToolkit
file.encoding = UTF-8
file.separator = /
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
java.awt.printerjob = sun.print.PSPrinterJob
java.class.path = /mnt/c/Workspace/library/java/
.
/home/fred/.local/share/py4j/py4j0.10.7.jar
java.class.version = 55.0
java.home = /usr/lib/jvm/java-11-openjdk-amd64
java.io.tmpdir = /tmp
java.library.path = /mnt/c/Workspace/build/library/
试图解决问题
确保我有一个有效的本地库
做一个
ls
/mnt/c/Workspace/build/library/
显示库
libMngr.so
.
如果我删除
李布尼格·索
从那个位置,然后试着运行Java抱怨它找不到库。
做
nm
命令打开
李布尼格·索
显示以下内容:
000000000021f269 T Java_com_mgr_1api_1JNI_createInstance
做
objdump
命令:
$objdump -f build/library/libMngr.so
build/library/libMngr.so: file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x000000000018aee0
显示本机库是64位的,并且根据
-XshowSettings:属性
我正在使用64位Java。
System.loadLibrary("Mngr");
在里面
mgr_api_JNI.java
以确保只加载一次本机库。
更新
api_JNI.java经理
并将函数声明复制到
.cpp
确保我有有效的Java类
如果我做一个
负载感应
在java.class.path上
/mnt/c/Workspace/library/java/
我从编译中找到了所有的Java类
api_JNI.java经理
.
如果我删除这些类并尝试运行Java,那么Java会抱怨它找不到这些类。
做一个
grep -r createInstance
在java.class.path上
返回:
Binary file com/mgr_api_JNI.class matches
com/mgr_api_JNI.java: public native void createInstance(com.mgr_api_types.EDisplayType displayType,
所以Java可以找到编译后的Java类
createInstance
方法。
问题
在我看来,Java可以找到所有需要的类和本机库,但我仍然得到
UnsatisfiedLinkError
错误。
为什么我还是会犯这个错误?
我需要做什么来帮助Java找到/识别
创建实例
方法?