java 调用原生方法时返回java.lang.UnsatisfiedLinkError
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11420153/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.lang.UnsatisfiedLinkError returned when calling native method
提问by yodal
I am trying to make a Java wrapper for a third party DLL. I created my own DLL that acts as a middle man between JNI and the third party DLL. In java I load this DLL fine but the error java.lang.UnsatisfiedLinkError: sixense.Sixense.init()Z
is returned. What could be causing this error and how can I debug it properly?
我正在尝试为第三方 DLL 制作 Java 包装器。我创建了自己的 DLL,充当 JNI 和第三方 DLL 之间的中间人。在 java 中,我很好地加载了这个 DLL,但java.lang.UnsatisfiedLinkError: sixense.Sixense.init()Z
返回了错误。什么可能导致此错误以及如何正确调试它?
Main.java:
主.java:
package sixense_test;
import sixense.ControllerData;
import sixense.Sixense;
public class Main {
public static ControllerData[] controllers = new ControllerData[4];
public static boolean quit;
public static void main(String[] args) {
if(Sixense.init()) {
Sixense.setActiveBase(0);
Sixense.getAllNewestData(controllers);
System.out.println("X: " + controllers[0].pos[0] + "Y: " + controllers[0].pos[1] + "Z: " + controllers[0].pos[2]);
}
}
}
Sixense.java:
Sixense.java:
package sixense;
public class Sixense {
public static native boolean init();
public static native boolean exit();
public static native int getMaxBases();
public static native boolean setActiveBase( int base_num );
public static native boolean isBaseConnected( int base_num );
public static native int getMaxControllers();
public static native int getNumActiveControllers();
public static native boolean isControllerEnabled( int controller_id );
public static native boolean getAllNewestData( ControllerData[] all_data );
public static native boolean getAllData( int index_back, ControllerData[] all_data );
public static native boolean getNewestData( int controller_id, ControllerData data );
public static native boolean getData( int controller_id, int index_back, ControllerData all_data );
public static native int getHistorySize();
public static native boolean setFilterEnabled( boolean on_or_off );
public static native boolean getFilterEnabled();
public static native boolean setFilterParams( float near_range, float near_val, float far_range, float far_val );
public static native boolean getFilterParams( float[] params );
public static native boolean triggerVibration( int controller_id, int duration, int pattern_id );
public static native boolean autoEnableHemisphereTracking( int controller_id );
public static native boolean setHighPriorityBinding( boolean on_or_off );
public static native boolean getHighPriorityBinding();
public static native boolean setBaseColor( int red, int green, int blue );
public static native boolean getColorBase( int[] colors );
static {
System.loadLibrary("Sixense_Java");
}
}
An excerpt from sixense_Sixense.cpp:
Sixense_Sixense.cpp 的摘录:
#include <jni.h>
#include <sixense.h>
#include "sixense_Sixense.h"
JNIEXPORT jboolean JNICALL Java_sixense_Sixense_init(JNIEnv *env, jclass obj) {
int i;
i = sixenseInit();
return (i == -1) ? JNI_FALSE : JNI_TRUE;
}
An excerpt from sixense_Sixense.h:
Sixense_Sixense.h 的摘录:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class sixense_Sixense */
#ifndef _Included_sixense_Sixense
#define _Included_sixense_Sixense
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: sixense_Sixense
* Method: init
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_sixense_Sixense_init
(JNIEnv *, jclass);
Output from dumpbin:
转储箱的输出:
File Type: DLL
Section contains the following exports for Sixense_Java.dll
00000000 characteristics
4FFBC481 time date stamp Tue Jul 10 01:58:25 2012
0.00 version
1 ordinal base
23 number of functions
23 number of names
ordinal hint RVA name
1 0 00001D10 Java_sixense_Sixense_autoEnableHemisphereTracking@12
2 1 000011A0 Java_sixense_Sixense_exit@8
3 2 00001A40 Java_sixense_Sixense_getAllData@16
4 3 000019A0 Java_sixense_Sixense_getAllNewestData@12
5 4 00001DC0 Java_sixense_Sixense_getColorBase@12
6 5 00001B30 Java_sixense_Sixense_getData@20
7 6 00001BD0 Java_sixense_Sixense_getFilterEnabled@8
8 7 00001C40 Java_sixense_Sixense_getFilterParams@12
9 8 00001D60 Java_sixense_Sixense_getHighPriorityBinding@8
10 9 00001B90 Java_sixense_Sixense_getHistorySize@8
11 A 000011C0 Java_sixense_Sixense_getMaxBases@8
12 B 00001210 Java_sixense_Sixense_getMaxControllers@8
13 C 00001AE0 Java_sixense_Sixense_getNewestData@16
14 D 00001220 Java_sixense_Sixense_getNumActiveControllers@8
15 E 00001180 Java_sixense_Sixense_init@8
16 F 000011F0 Java_sixense_Sixense_isBaseConnected@12
17 10 00001230 Java_sixense_Sixense_isControllerEnabled@12
18 11 000011D0 Java_sixense_Sixense_setActiveBase@12
19 12 00001D90 Java_sixense_Sixense_setBaseColor@20
20 13 00001BA0 Java_sixense_Sixense_setFilterEnabled@12
21 14 00001C00 Java_sixense_Sixense_setFilterParams@24
22 15 00001D30 Java_sixense_Sixense_setHighPriorityBinding@12
23 16 00001CE0 Java_sixense_Sixense_triggerVibration@20
Summary
1000 .bss
1000 .data
1000 .edata
1000 .idata
1000 .rdata
1000 .reloc
2000 .text
回答by RudolfW
When calling a native function in Java, the runtime tries to use:
在 Java 中调用本机函数时,运行时会尝试使用:
- a stdcall-style decorated function:
_functionName@n
, where n is the number of bytes in the parameter list, - and a cdecl-style undecorated function:
functionName
.
- 一个 stdcall 风格的装饰函数:
_functionName@n
,其中 n 是参数列表中的字节数, - 和 cdecl 风格的未修饰函数:
functionName
.
When compiling with MinGW, you will get a mix of these two: MinGW will append the @n
, but will not prepend the underscore: functionName@n
.
使用 MinGW 进行编译时,您将获得这两者的混合:MinGW 将附加@n
,但不会预先添加下划线:functionName@n
。
The way to solve this is to tell ld
not to add the suffix, using the --kill-at
switch (or -Wl,--kill-at
if you call it through GCC).
解决这个问题的方法是告诉ld
不要添加后缀,使用--kill-at
开关(或者-Wl,--kill-at
如果你通过 GCC 调用它)。
回答by yodal
I have found the answer! It seems that when using JNI in Windows it looks for a function starting with _Java_
while in every other platform it looks for Java_
. Why this is the case and not written in the documentation I don't know but it make everything work perfectly!
我找到了答案!似乎在 Windows 中使用 JNI 时,它会在它寻找的_Java_
所有其他平台中查找以while开头的函数Java_
。为什么会这样,而不是写在文档中我不知道,但它使一切正常!
回答by Brainbot
java.lang.UnsatisfiedLinkError: no Sixense_Java in java.library.path
Looks like Java cant find the library, did you put it in the right place?
看起来Java找不到库,你把它放在正确的地方了吗?
You might need to change the java.library.path
, take a look at this.
你可能需要改变java.library.path
,看看这个。
If you want to print the contents of it use:
如果要打印它的内容,请使用:
System.out.println( System.getProperties().getProperty("java.library.path"));
This might print a lot, you might want to split(";")
and print each entry on its own.
这可能会打印很多,您可能希望自己split(";")
打印每个条目。