- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在使用 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 以及其他链接,但它们都没有解决我的问题。
mgr_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);
}
testsJNI.java:
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(通过在 mgr_api_JNI.java 上使用 javac -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/
在 java.library.path /mnt/c/Workspace/build/library/
上执行 ls
显示库 libMngr.so
.
如果我从该位置删除 libMngr.so
,然后尝试运行 Java,则会提示找不到该库。
在 libMngr.so
上执行 nm
命令显示以下内容:
000000000021f269 T Java_com_mgr_1api_1JNI_createInstance
所以Java可以找到native library,它有函数的符号。
执行 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
显示 native 库是 64 位的,根据 -XshowSettings:properties
我使用的是 64 位 Java。
我什至在 mgr_api_JNI.java
中的 System.loadLibrary("Mngr");
之前放置了一条打印语句,以确保只加载一次 native 库.
我已经从 mgr_api_JNI.java
重新生成头文件并将函数声明复制到 .cpp
文件以确保函数名称是正确的。但我仍然遇到同样的错误。
如果我在 java.class.path /mnt/c/Workspace/library/java/
上执行 ls
,我会从编译中找到所有 Java 类 mgr_api_JNI.java
。
如果我删除这些类并尝试运行 Java,那么 Java 会提示找不到这些类。
在 java.class.path /mnt/c/Workspace/library/java/
上执行 grep -r createInstance
返回:
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 可以找到所有需要的类和 native 库,但我仍然收到 UnsatisfiedLinkError
错误。
为什么我仍然收到此错误?
我需要做什么来帮助 Java 找到/识别 createInstance
方法?
最佳答案
这是你的错误
你有库文件:/mnt/c/Workspace/build/library/libMgr.so
但你在代码中加载了这个文件:System.loadLibrary("Mngr");
- 你打错了
您可以确保在名称正确的情况下它按预期工作
当您“离开”初始 JVM
时,-Djava.library.path
不再是向其他 JVM 提供信息的有效位置。我不知道 py4j.GatewayConnection
的详细信息,但最好确保您不运行另一个 JVM
实例,或者您不使用 JNI
那里。
我建议进行以下测试:
将 LD_LIBRARY_PATH
设置为您的库所在的位置
确保您可以仅使用public class mgr_api_JNI
(没有 Python 桥接引擎)访问代码中的库
如果您的第二个 JVM 有可能正在加载 native 代码(但找不到它),请尝试使用 _JAVA_OPTIONS=-Djava.library.path=[path to library]
。这样,所有 JVM
都会“看到”该位置 - 但您应该这样做只是为了测试目的
从另一个进程加载 lib 看起来确实有问题。如果我将您的代码缩减为如下内容:
.
|-- Makefile
|-- README.md
|-- c
| `-- com_mgr_api_JNI.cc
|-- java
| `-- com
| |-- mgr_api_JNI.java
| `-- mgr_api_types
| |-- ECommType.java
| `-- EDisplayType.java
|-- lib
`-- target
和代码本身
com_mgr_api_JNI.cc
#include <iostream>
#include "jni.h"
#include "com_mgr_api_JNI.h"
using namespace std;
JNIEXPORT void JNICALL Java_com_mgr_1api_1JNI_createInstance
(JNIEnv *env, jobject cls, jobject a, jstring b, jobject c, jstring d) {
cout << "Hello";
}
java/com/mgr_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);
public static void main(String [] arg) {
mgr_api_JNI obj = new mgr_api_JNI();
obj.createInstance(new com.mgr_api_types.EDisplayType(), "", new com.mgr_api_types.ECommType(), "");
}
}
java/com/mgr_api_types/ECommType.java
package com.mgr_api_types;
public class ECommType { }
cat java/com/mgr_api_types/EDisplayType.java
package com.mgr_api_types;
public class EDisplayType { }
然后我构建代码
Makefile.common
ARCH=$(shell uname -s | tr '[:upper:]' '[:lower:]')
ifeq ($(ARCH),darwin)
EXT=dylib
else
EXT=so
endif
生成文件
include Makefile.common
all: compilejava compilec
compilec:
c++ -std=c++11 -g -shared -fpic -I${JAVA_HOME}/include -I${JAVA_HOME}/include/$(ARCH) c/com_mgr_api_JNI.cc -o lib/libMngr.$(EXT)
compilejava:
$(JAVA_HOME)/bin/javac -h c -d target -cp target java/com/mgr_api_types/EDisplayType.java
$(JAVA_HOME)/bin/javac -h c -d target -cp target java/com/mgr_api_types/ECommType.java
$(JAVA_HOME)/bin/javac -h c -d target -cp target java/com/mgr_api_JNI.java
test:
$(JAVA_HOME)/bin/java -Djava.library.path=$(LD_LIBRARY_PATH):./lib -cp target com.mgr_api_JNI
clean:
-rm -rfv target/*
-rm c/*.h
-rm -rf lib/*
它按预期工作
make test
/Library/Java/JavaVirtualMachines/jdk-12.0.1.jdk/Contents/Home/bin/java -Djava.library.path=:./lib -cp target com.mgr_api_JNI
Hello
我认为你有这样一种情况,你的类是从另一个 JVM 实例,或者从通过 JNI 调用的东西,或者从另一个进程调用的,而你的 -Djava.library.path
不见了。
此外,尝试使用 System.load("full/path/of/library.so")
确保您可以从 JVM
访问该库。
关于java.lang.UnsatisfiedLinkError 即使库和类有方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56507951/
在 Tomcat 6/Ubuntu 12.04 上启动 Grails 2.1.0 应用程序时出现以下错误。 Error 500 - Internal Server Error. groovy.lang
在运行 Storm 拓扑时,我收到此错误。拓扑完美运行 5 分钟,没有任何错误,然后失败。我正在使用 Config.TOPOLOGY_TICK_TUPLE_FREQ_SECS as 300 sec i
我有一个 jsp 代码在其中一台机器上运行良好。但是当我复制到另一台机器时,我得到了这个 no such method found 异常。我是 Spring 的新手。有人可以解释我错过了什么吗? 以下
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我的代码在下面给出了一个错误; Exception in thread "main" java.lang.NoSuchMethodError: com/myApp/Client.cypherCBC(L
我正在尝试一个 Restful web 服务示例,所以当我要访问 url 时,我遇到了异常 java.lang.NoSuchMethodError: jersey.repackaged.com.goo
我正在将一个 Spring web 项目转换为一个 Maven 项目,但我收到了这个错误: java.lang.NoSuchMethodError: org.jboss.logging.Logger.
在我的项目中,我有一个像这样的枚举: public enum MyEnum { FIRST(1), SECOND(2); private int value; private MyEnum(int v
我创建了这个简单的示例,用于读取 Linux 正常运行时间: public String getMachineUptime() throws IOException { String[] di
我正在使用 Eclipse,并且正在使用 Java。我的目标是使用 bogoSort 方法对 vector 进行排序在一个 vector (vectorExample)中适应我的 vector 类型,
我正在运行以下查询。它显示一条错误消息。如何解决这个错误? ListrouteList=null; List companyList = session.createS
我有以下模型类: @Entity @Table(name="user_content") @org.hibernate.annotations.NamedQueries({ @org.
我有那个错误。这是我的代码: GmailSettingsService service = new GmailSettingsService(APPLICATION_NAME, DOMAIN_NAME
实际上我在执行我的java程序时遇到了下面提到的错误 Exception in thread "pool-1-thread-1" java.lang.ClassCastException: jav
java.lang.ClassCastException: java.lang.Float cannot be cast to java.lang.String 我在以下代码中遇到此异常: Strin
我正在尝试从 linkedhashset 中检索随机元素。下面是我的代码,但它每次都给我异常。 private static void generateRandomUserId(Set userIds
我已经完成了 Android 中的代码: List spinnerArray = new ArrayList(); for (int i = 0; i item = (LinkedTreeMap)
这个问题已经有答案了: Explanation of ClassCastException in Java (12 个回答) 已关闭 6 年前。 我已经编写了 java 到 Json 的代码,同时从页
这个问题在这里已经有了答案: ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn (4 个答案) 关闭 6 年前
我在运行时遇到问题来编译这段代码,这给我一个错误,java.lang.Integer 无法转换为 Java.lang.Double。如果有人帮助我更正此代码,我将非常高兴 double x; pu
我是一名优秀的程序员,十分优秀!