The Java Native Interface (JNI) enables the integration of code written in the Java programming language with code written in other languages such as C, C++ and assembly. Therefore, you can natively run heavy tasks in pursuance of a better performance.
Is it platform-independent?
Your application can be platform-independent if you store the compiled JNI libraries (for all possible architectures) in the jar alongside the class files. However, since System.load() can't cope with loading libraries from within a jar, you'll therefore need a custom loader which extracts the library to a temporary file at runtime.
So, what do I need ?
And, which are the magic steps?
Is it platform-independent?
Your application can be platform-independent if you store the compiled JNI libraries (for all possible architectures) in the jar alongside the class files. However, since System.load() can't cope with loading libraries from within a jar, you'll therefore need a custom loader which extracts the library to a temporary file at runtime.
So, what do I need ?
- Microsoft Windows SDK (recomended if you are using Windows)
- Microsoft Visual Studio (same here)
- Java SDK
And, which are the magic steps?
1. Declare your native methods in a normal Java class.
public class JavaJNI {
static {
System.loadLibrary("NativeLib");
}
public static native String write(String s);
public static void main(String[] argv) {
System.out.print(JavaJNI.write("Hello"));
}
}
2. Compile the Java file normally.
javac JavaJNI.java
3. Generate the .h file.
javah -jni JavaJNI
4. Write the native code using the file generated above.
In this case you will find the following method inside:
JNIEXPORT jstring JNICALL Java_JavaJNI_write(JNIEnv *, jclass, jstring);Now you have the green light to implement it.
#include "JavaJNI.h"
JNIEXPORT jstring JNICALL Java_JavaJNI_write(JNIEnv *env,
jobject thisobject, jstring js){
const char *temp;
jstring result = NULL;
temp = (*env)->GetStringUTFChars(env, js, 0);
/** Your normal C code */
printf("Input: %s", temp);
result = (*env)->NewStringUTF(env,
(const char*) "\nResult: http://www.think-techie.com");
(*env)->ReleaseStringUTFChars(env, js, temp);
return result;
}
If you are trying to use C++ use the following methods instead:env->GetStringUTFChars(js, 0); env->NewStringUTF((const char*) temp); env->ReleaseStringUTFChars(js, temp);
5. Compile the code
Windows with MS C++ Compiler
cl -c /Ic:\Programs\JavaSDK\include /I"C:\Programs\Microsoft Visual Studio 9.0\VC\include" /Ic:\Programs\JavaSDK\include\win32 NativeLib.c link -LIBPATH:"C:\Programs\Microsoft SDKs\Windows\v6.0\VC\LIB" -LIBPATH:"C:\Programs\Microsoft SDKs\Windows\v6.0\Lib" NativeLib.obj /dllOr this one:
cl -I C:\Programs\JavaSDK\include -I C:\Programs\JavaSDK\include\win32 -LD NativeLib.c -FeNativeLib.dllSolaris with Sun Compiler
cc -G -I JavaSDK/include -I JavaSDK/include/solaris -o libNativeLib.so NativeLib.cLinux with GCC
gcc -fPIC -I JavaSDK/include -I JavaSDK/include/linux -shared -o libNativeLib.so NativeLib.cIf your prefer to use Ant take a look at cc Task.
6. Run the example
java JavaJNIApplication output:
Input: Hello Result: http://www.think-techie.com7. Did you got errors ?
There are some common errors such as:
java.lang.UnsatisfiedLinkError: no NativeLib in java.library.path at java.lang.ClassLoader.loadLibrary(Unknown Source) at java.lang.Runtime.loadLibrary0(Unknown Source) at java.lang.System.loadLibrary(Unknown Source) at ...The manner through which java searches for the needed files are different in each scenario:
- Java searches for *.class files through the "-cp"/"-classpath" command line switch. If neither are specified on the command line, CLASSPATH is searched.
- Java searches for JNI files through the "-Djava.library.path" command line switch. If "-Djava.library.path" is not specified, LD_LIBRARY_PATH is searched, but the /etc/ld.so.conf mechanism is not used.
- The way a JNI glue library searches for the underlying C++ *.so libraries is not controlled by the Java process at all. The normal operating system rules are applied (LD_LIBRARY_PATH, /etc/ld.so.conf, etc.).
LD_LIBRARY_PATH=`pwd` export LD_LIBRARY_PATHAnother way is to define the location when running the program:
java -Djava.library.path=. JavaJNI8. Did you got more errors ?
java.lang.UnsatisfiedLinkError: <library location>: <library location>: only ET_DYN and ET_EXEC can be loaded at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1778) at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1674) at java.lang.Runtime.load0(Runtime.java:770) at java.lang.System.load(System.java:1005) ...If you are using g++, try to include the option "-shared" when compiling the cpp file.
g++ -shared NativeLib.cpp -o NativeLib.so -I JavaSDK/include -I JavaSDK/include/linuxDo not include the "-c" option. It will skip the linking stage.
References
[1] JNI – Java Native Interface. White Magician. wmagician.wordpress.com


0 comments:
Post a Comment