调用本机方法时返回java.lang.UnsatisfiedLinkError

我正在尝试为第三方DLL制作Java包装器。 我创建了自己的DLL,充当JNI和第三方DLL之间的中间人。 在java中我加载此DLL很好,但返回错误java.lang.UnsatisfiedLinkError: sixense.Sixense.init()Z . 可能导致此错误的原因以及如何正确调试?

Main.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:

 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"); } } 

摘自sixense_Sixense.cpp:

 #include  #include  #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; } 

摘自sixense_Sixense.h:

 /* DO NOT EDIT THIS FILE - it is machine generated */ #include  /* 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); 

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 

在Java中调用本机函数时,运行时会尝试使用:

  • stdcall样式的装饰函数: _functionName@n ,其中n是参数列表中的字节数,
  • 和一个cdecl风格的未修饰函数: functionName

在使用MinGW进行编译时,您将得到这两者的混合:MinGW将追加@n ,但不会添加下划线: functionName@n @n

解决这个问题的方法是告诉ld不要添加后缀,使用--kill-at开关(或--kill-at -Wl,--kill-at如果你通过GCC调用它-Wl,--kill-at则为-Wl,--kill-at )。

我找到了答案! 似乎在Windows中使用JNI时,它会查找以_Java_开头的函数,而在其他所有平台中查找Java_ 。 为什么会出现这种情况,而不是写在我不知道的文档中,但它会使一切运行完美!

 java.lang.UnsatisfiedLinkError: no Sixense_Java in java.library.path 

看起来Java无法找到库,你把它放在了正确的位置吗?

您可能需要更改java.library.path ,看看这个 。

如果要打印它的内容,请使用:

 System.out.println( System.getProperties().getProperty("java.library.path")); 

这可能打印很多,你可能想要split(";")并自己打印每个条目。