Reputation: 1438
I am trying to call a simple native method in Java from C++, to achieve this I do the following:
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");
}
}
Create .h file for the native method using javah -jni
which create the following declaration:
JNIEXPORT void JNICALL Java_HelloNative_printString(JNIEnv *, jobject, jstring);
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);
}
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
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
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
Reputation: 57326
I recommend to load the library slightly differently.
Place your libmynative.so
into whatever directory you like.
Add that directory to LD_LIBRARY_PATH
variable.
In your java code, change System.load
call to be System.loadLibrary("mynative")
(note the lack of full path, prefix lib and extension .so)
Run your java code.
Have a look here for more details: http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html
Upvotes: 1