Java: Invoking native method giving «Exception in thread «main» java.lang.UnsatisfiedLinkError»
But when I compile and run the .java file it’s giving me Runtime Exception:
Current Directory is: /home/gmuhammad/Projects/test Calling Native Libraray (libhellonative.so) method printString Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloNative.printString(Ljava/lang/String;)V at HelloNative.printString(Native Method) at HelloNative.main(HelloNative.java:16)
3 Answers 3
Ok, I got this to work. It has nothing to do with loading the library, but with actually calling the method from that library.
I created .java , .h and .cpp files by copy/paste from your question and ran them (I had to add #include in the .cpp file) — and got exactly the same error as you did.
Then I edited the .cpp file to include the generated .h file. Also, as maba indicated in his answer, you need to call (jni_env)->ReleaseStringUTFChars(msg, message); to release the object. My full .cpp file now looks like this:
#include "HelloNative.h" JNIEXPORT void JNICALL Java_HelloNative_printString(JNIEnv* jni_env, jobject java_obj, jstring msg)< printf("inside native method\n"); jboolean iscopy; const char *message = (jni_env)->GetStringUTFChars( msg, &iscopy); printf("%s", message); (jni_env)->ReleaseStringUTFChars(msg, message); >
I re-compiled the library, ran the java code — and voila! everything works. This way, it works regardless of which way you load the library, with load or loadLibrary .
JNI- java.lang.UnsatisfiedLinkError: Native method not found
I’m developing an Android project using OpenCV. Some of the methods do not have Java version, so I have to use NDK to use them in my project. This is my first time using NDK, so after searching for some examples, I wrote my code, run it on my device, and received error message below:
07-04 10:26:19.555 21270-21270/com.example.MyTest E/AndroidRuntime﹕ FATAL EXCEPTION: main java.lang.UnsatisfiedLinkError: Native method not found: com.example.MyTest.JNIlib.readImg:()I at com.example.MyTest.JNIlib.readImg(Native Method) at com.example.MyTest.MyActivity$2.onClick(MyActivity.java:60) at android.view.View.performClick(View.java:4211) at android.view.View$PerformClick.run(View.java:17267) at android.os.Handler.handleCallback(Handler.java:615) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4898) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773) at dalvik.system.NativeStart.main(Native Method)
I regenerated .so files for several times, and check the naming for jni functions. I also added ‘extern «C»‘ wrappers to jni functions. But none of those solutions worked. Notice: I always use Intellij Idea to develop JAVA programs, and since Idea doesn’t support NDK, and I have to use Eclipse to get to NDK, so. this is also the first time I use Eclipse. I could have made a lot of silly mistakes. lol Below are my c++ codes and makefile. LocalMain.cpp
#include #include #include #include #include #include #include #include #include "LocalFeature.h" using namespace cv; using namespace std; int readImg() < /* do something*/ return 0; >// JNI interface functions, be careful about the naming. extern "C" < JNIEXPORT jint JNICALL Java_com_example_MyTest_JNIlib_readImg(JNIEnv * env, jobject obj); >; JNIEXPORT jint JNICALL Java_com_example_MyTest_JNIlib_readImg(JNIEnv * env, jobject obj)
LocalFeatures.h and LocalFeatures.cpp are not shown, but I’m sure the problem is not with them. Android.mk
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := nonfree_prebuilt LOCAL_SRC_FILES := libnonfree.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := opencv_java_prebuilt LOCAL_SRC_FILES := libopencv_java.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) # Modify LOCAL_C_INCLUDES with your path to OpenCV for Android. LOCAL_C_INCLUDES:= E:/Java/libs/OpenCV-2.4.9-android-sdk/sdk/native/jni/include LOCAL_MODULE := mytest_lib LOCAL_CFLAGS := -Werror -O3 -ffast-math LOCAL_LDLIBS += -llog -ldl LOCAL_SHARED_LIBRARIES := nonfree_prebuilt opencv_java_prebuilt LOCAL_SRC_FILES := LocalMain.cpp \ LocalFeature.h \ LocalFeature.cpp include $(BUILD_SHARED_LIBRARY)
Those .cpp files and .mk files are in an Eclipse project. libmytest_lib.so, libopencv_java.so, libnonfree.so can be correctly generated. The following .java files are in an Intellij Idea project. I have copied these .so files to \lib in the Idea project. JNIlib.java
public class JNIlib < static < try < // Load necessary libraries. System.loadLibrary("opencv_java"); System.loadLibrary("nonfree"); System.loadLibrary("mytest_lib"); >catch( UnsatisfiedLinkError e ) < System.err.println("Native code library error.\n"); >> public static native int readImg(); >
public class MyActivity extends Activity implements CameraBridgeViewBase.CvCameraViewListener2 < public View.OnClickListener onClickListener = new View.OnClickListener() < @Override public void onClick(View v) < JNIlib.readImg(); >>; /*Other irrevelant code*/ >
java.lang.UnsatisfiedLinkError returned when calling native method
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]); >> >
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"); >>
#include #include #include "sixense_Sixense.h" JNIEXPORT jboolean JNICALL Java_sixense_Sixense_init(JNIEnv *env, jclass obj)
/* 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);
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
What is the cause of an UnsatisfiedLinkError?
Thrown if the Java Virtual Machine cannot find an appropriate native-language definition of a method declared native.
It is an error related to JNI. loadJacobLibrary is trying to load the native library called jacob-1.14.3-x86 and it is not found on the path defined by java.library.path. This path should be defined as a system property when you start the JVM. e.g.
On Windows, the actual native library file will be called jacob-1.14.3-x86.dll while on Linux it would be called libjacob-1.14.3-x86.so
i would add that path should not end with slash/backslash - just with the name of the directory (oh god I was making this mistake)
You need the jacob-1.14.3-x86 library on your java library path.
On windows, this would be jacob-1.14.3-x86.dll.
This is a binary file which is used by java to run native methods. It's probably required by some library (jar) you're using.
In here you can see not only a jar, but also the binary required by the jar. Pick the one for your platform.
There are two things that cause UnsatisfiedLinkError. One is when System.loadLibrary() fails to load the library, the other is when the JVM fails to find a specific method in the library. The text of the error message itself will indicate which is the case.
The error which you describe clearly cannot find the library at all. As the others have said, include it in your Java library path.
The other error—when the library can be found but the method within the library is not found—looks as follows:
java.lang.UnsatisfiedLinkError: myObject.method([Ljava/lang/Object;)V
In this case you either have the wrong method name, or will have to go back and add the method and recompile the code.