java.lang.UnsatisfiedLinkError returned when calling native method
Solution 1
When calling a native function in Java, the runtime tries to use:
- 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
.
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
.
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).
Solution 2
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!
Solution 3
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?
You might need to change the java.library.path
, take a look at this.
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.
yodal
Updated on June 04, 2022Comments
-
yodal almost 2 years
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?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"); } }
An excerpt from 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:
/* 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