GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing en.wikibooks.org — Java Native Interface - Wikibooks, open books for an open world
JNI can be used:
On the other hand, an application that relies on JNI loses the platform portability Java offers. So you will have to write a separate implementation of JNI code for each platform and have Java detect the operating system and load the correct one at runtime. Many of the standard library classes depend on JNI to provide functionality to the developer and the user (file I/O, sound capabilities...). Including performance- and platform-sensitive API implementations in the standard library allows all Java applications to access this functionality in a safe and platform-independent manner. Only applications and signed applets can invoke JNI. JNI should be used with caution. Subtle errors in the use of JNI can destabilize the entire JVM in ways that are very difficult to reproduce and debug. Error checking is a must or it has the potential to crash the JNI side and the JVM. This page will only explain how to call native code from JVM, not how to call JVM from native code. Calling native code from JVMIn the JNI framework, native functions are implemented in separate .c or .cpp files. C++ provides a slightly simpler interface with JNI. When the JVM invokes the function, it passes a JNIEXPORT void JNICALL Java_ClassName_MethodName (JNIEnv* env, jobject obj) { /*Implement Native Method Here*/ } The On Linux and Solaris platforms, if the native code registers itself as a signal handler, it could intercept signals intended for the JVM. Signal chaining should be used to allow native code to better interoperate with JVM. On Windows platforms, Structured Exception Handling (SEH) may be employed to wrap native code in SEH try/catch blocks so as to capture machine (CPU/FPU) generated software interrupts (such as NULL pointer access violations and divide-by-zero operations), and to handle these situations before the interrupt is propagated back up into the JVM (i.e. Java side code), in all likelihood resulting in an unhandled exception. C++ codeFor example, the following converts a Java string to a native string: extern "C" JNIEXPORT void JNICALL Java_ClassName_MethodName (JNIEnv* env, jobject obj, jstring javaString) { //Get the native string from javaString const char* nativeString = env->GetStringUTFChars(javaString, 0); //Do something with the nativeString //DON'T FORGET THIS LINE!!! env->ReleaseStringUTFChars(javaString, nativeString); } The JNI framework does not provide any automatic garbage collection for non-JVM memory resources allocated by code executing on the native side. Consequently, native side code (such as C, C++, or assembly language) must assume the responsibility for explicitly releasing any such memory resources that it itself acquires. C codeJNIEXPORT void JNICALL Java_ClassName_MethodName (JNIEnv* env, jobject obj, jstring javaString) { /*Get the native string from javaString*/ const char* nativeString = (*env)->GetStringUTFChars(env, javaString, 0); /*Do something with the nativeString*/ /*DON'T FORGET THIS LINE!!!*/ (*env)->ReleaseStringUTFChars(env, javaString, nativeString); } Note that C++ JNI code is syntactically slightly cleaner than C JNI code because like Java, C++ uses object method invocation semantics. That means that in C, the Objective-C codeJNIEXPORT void JNICALL Java_ClassName_MethodName(JNIEnv *env, jobject obj, jstring javaString) { /*DON'T FORGET THIS LINE!!!*/ JNF_COCOA_ENTER(env); /*Get the native string from javaString*/ NSString* nativeString = JNFJavaToNSString(env, javaString); /*Do something with the nativeString*/ /*DON'T FORGET THIS LINE!!!*/ JNF_COCOA_EXIT(env); } JNI also allows direct access to assembly code, without even going through a C bridge. Mapping typesNative data types can be mapped to/from Java data types. For compound types such as objects, arrays and strings the native code must explicitly convert the data by calling methods in the
In addition, the signature However, mapping between Java Strings and arrays to native strings and arrays is different. If you use a JNIEXPORT void JNICALL Java_ClassName_MethodName (JNIEnv* env, jobject obj, jstring javaString) { // printf("%s", javaString); // INCORRECT: Could crash VM! // Correct way: Create and release native string from Java string const char* nativeString = (*env)->GetStringUTFChars(env, javaString, 0); printf("%s", nativeString); (*env)->ReleaseStringUTFChars(env, javaString, nativeString); } The encoding used for the The code is similar with Java arrays, as illustrated in the example below that takes the sum of all the elements in an array. JNIEXPORT jint JNICALL Java_IntArray_sumArray (JNIEnv *env, jobject obj, jintArray arr) { jint buf[10]; jint i, sum = 0; // This line is necessary, since Java arrays are not guaranteed // to have a continuous memory layout like C arrays. env->GetIntArrayRegion(arr, 0, 10, buf); for (i = 0; i < 10; i++) { sum += buf[i]; } return sum; } Of course, there is much more to it than this. JNIEnv*A JNI environment pointer ( To attach to the current thread and get a JNI interface pointer: JNIEnv *env; (*g_vm)->AttachCurrentThread (g_vm, (void **) &env, NULL); To detach from the current thread: (*g_vm)->DetachCurrentThread (g_vm); HelloWorld
HelloWorld.h /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class HelloWorld */ #ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern "C" { #endif /* * Class: HelloWorld * Method: print * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif libHelloWorld.c #include <stdio.h> #include "HelloWorld.h" JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj) { printf("Hello World!\n"); return; } make.sh #!/bin/sh # openbsd 4.9 # gcc 4.2.1 # openjdk 1.7.0 JAVA_HOME=$(readlink -f /usr/bin/javac | sed "s:bin/javac::") export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. javac HelloWorld.java javah HelloWorld gcc -I${JAVA_HOME}/include -shared libHelloWorld.c -o libHelloWorld.so java HelloWorld
Advanced usesNot only can native code interface with Java, it can also draw on a
| |||||||||||||||||||||||||||||||||||||||||
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |