gmuhammad
gmuhammad

Reputation: 1438

Java: Invoking native method giving "Exception in thread "main" java.lang.UnsatisfiedLinkError"

I am trying to call a simple native method in Java from C++, to achieve this I do the following:

  1. Create a simple class as shown below:

    public class HelloNative{
       public native void printString(String str);
       static{
            System.out.println("Current Directory is: " + System.getProperty("user.dir"));
            System.load(System.getProperty("user.dir") + "/libhellonative.so");
        }
        public static void main(String[] args){
            System.out.println("Calling Native Libraray (libhellonative.so) method printString");
            new HelloNative().printString("Message from Java to C");
         }
    }
    
  2. Create .h file for the native method using javah -jni which create the following declaration:

    JNIEXPORT void JNICALL Java_HelloNative_printString(JNIEnv *, jobject, jstring);

  3. Implement the native function in .cpp file as:

    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);
    }
    
  4. And finally create the .so file using:

    g++ HelloNative.cpp -o libhellonative.so -shared -Wl,-soname,libhellonative.so -static -lc -I /usr/lib/jvm/java-6-sun-1.6.0.26/include -I /usr/lib/jvm/java-6-sun-1.6.0.26/include/linux

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)

Upvotes: 1

Views: 3956

Answers (3)

Aleks G
Aleks G

Reputation: 57326

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 <jni.h> 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.

Give it a try.

Upvotes: 3

maba
maba

Reputation: 48075

It is totally OK to use the System.load() but you will have to be sure that your shared libraries really are where you say they should be.

Current Directory is: /home/gmuhammad/Projects/test

Your code is trying to access the shared library in that directory. Are you sure that the libhellonative.so is there?

Then you can also use the System.mapLibraryName("hellonative") to get the name of the shared library for the current platform. That makes it more platform independent. The call will give you libhellonative.so on linux and hellonative.dll on windows.

Also you must call (jni_env)->GetReleaseUTFChars(msg, message); to release the objects.

Upvotes: 1

Aleks G
Aleks G

Reputation: 57326

I recommend to load the library slightly differently.

  1. Place your libmynative.so into whatever directory you like.

  2. Add that directory to LD_LIBRARY_PATH variable.

  3. In your java code, change System.load call to be System.loadLibrary("mynative") (note the lack of full path, prefix lib and extension .so)

  4. Run your java code.

Have a look here for more details: http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html

Upvotes: 1

Related Questions