Platform | Tool Documentation | local copy |
---|---|---|
Solaris, Linux | javah | javah |
Windows | javah | javah |
native return type method (arguments);
include/jni.h
static { System.loadLibrary("dynamic libary"); }
action | GNU | Windows |
---|---|---|
compile | gcc | cl |
link | ln | link |
action | Solaris | Windows |
---|---|---|
compile | -G | /LD |
link | -G | /dll |
library file | libname.so | name.dll |
javac HelloWorld.java
javah -jni HelloWorldHelloWorld.h include include/jni.h in the Java system install directory. jni.h contains C/C++ function prototypes and includes system dependent file jni_md.h.
jni.h
gcc -I/software/java/jdk1.2.2/include -I/software/java/jdk1.2.2/include/solaris -c HelloWorld.c -o HelloWorld.o
ld -G HelloWorld.o -o libHelloWorld.so
java -Djava.library.path=. HelloWorld Hello World!(Could do
setenv LD_LIBRARY_PATH .
on Unix instead.)
The current directory "." appears to be on the default path used
by Java to load libraries.
JNIEXPORT void JNICALL Java_ ... (JNIENV *env, ...) { (*env)->GetFieldID (env, ...); }
JNIEXPORT void JNICALL Java_ ... (JNIENV *env, ...) { env->GetFieldID (...); }
> java -Djava.library.path=. Access A private variable = 0 A private variable = 97 A static private variable = 0 A static private variable = 101
jclass c = (*env)->GetObjectClass(env, this); jfieldID fid = (*env)->GetFieldID(env, c, "private_variable", "I"); (*env)->SetIntField (env, this, fid, val);
jclass c = (*env)->GetObjectClass(env, this); jfieldID fid = (*env)->GetFieldID(env, c, "private_variable", "I"); jint val = (*env)->GetIntField(env, this, fid);
jclass c = (*env)->GetObjectClass(env, this);
JNIEXPORT void JNICALL Java_AccessOther_setPrivate (JNIENV *env, jobject this, jobject other, jint val) { jclass c = (*env)->GetObjectClass(env, other); }
Java Type | JNI Type | machine dependent C/C++ typedef | Signature | Call...Method Get...Field |
---|---|---|---|---|
boolean | jboolean | unsigned char | Z | Boolean |
byte | jbyte | signed char | B | Byte |
char | jchar | unsigned short | C | Char |
short | jshort | short | S | Short |
int | jint | int | I | Int |
long | jlong | long | J | Long |
float | jfloat | float | F | Float |
double | jdouble | double | D | Double |
void | void | V | Void | |
nonprimitive | jobject | * ... | L...; | Object
|
method definition | signature |
---|---|
int m1 () | ()I |
double m2 (long l, char c) | (JC)D |
void m3 (String s, int[] a) | (Ljava/lang/String;[I)V |
String m4 (boolean b) | (Z)Ljava/lang/String; |
Object m4 (BigDecimal b) | (Ljava/math/BigDecimal;)Ljava/lang/Object; |
private String getLine (String) (Ljava/lang/String;)Ljava/lang/String; public static void main (String [] args) ([Ljava/lang/String;)V
getMethodID (JNIEnv, jclass, char* name, char* descriptor)
There are three forms of calling a Java method:
JNI type CalltypeMethod (jobject, jmethodID, arguments); JNI type CallStatictypeMethod (jobject, jmethodID, arguments); JNI type CallNonvirtualtypeMethod (jobject, jmethodID, arguments);
Constructors are named <inti>.
There are three forms for passing the unknown number of arguments:
jvalue*
(an array)
va_list
JNItypeCalltypeMethod (jobject obj, jmethodID mid, ...); JNItypeCalltypeMethodA (jobject obj, jmethodID mid, jvalue* args); JNItypeCalltypeMethodV (jobject obj, jmethodID mid, va_list args);
NewObjectArray GetArrayLength SetObjectElement
JNIEXPORT jstring JNICALL Java_Strings_printString (JNIEnv *env, jclass this, jstring str) { const char* utf_string; jboolean is_copy; utf_string = env->GetStringUTFChars (str, &isCopy); printf ("%s\n", utf_string); if (isCopy == JNI_TRUE) { env->ReleaseStringUTFChars (str, utf_string); } }How to create a Java string in native code:
JNIEXPORT jstring JNICALL Java_NewString_newStringUTF (JNIEnv *env, jclass this) { const char* msg = "String constructed using NewStringUTF"; return env->NewStringUTF(msg); }
jclass cls = (*env)->FindClass (env, "java/lang/IllegalArgumentException"); if (cls==NULL) return; // Give up (*env)->ThrowNew (env, cls, "message"); return;
(*env)->CalltypeMethod (env, obj, method_id) jthrowable exc = (*env)->ExceptionOccurred(env) if (exc) { (*env)->ExceptionClear(env) }
int main (int argc, char *argv[]) { JNIEnv *env; JavaVM *jvm; int i; JDK1_1InitArgs vm_args; // env variables to control invocation jint ret; jmethodID mid; vm_args.version = 0x00010001; JNI_GetDefaultJavaVMInitArgs(&vm_args); int len = strlen(MY_CLASSPATH) + strlen(vm_args.classpath) + 1; char * newcp = (char*) malloc(len * sizeof(char)); strcpy(newcp, MY_CLASSPATH); strcat(newcp, vm_args.classpath); vm_args.classpath = newcp; vm_args.properties = properties; vm_args.vfprintf = y_fprintf; vm_args.exit = y_exit; vm_args.abort = y_abort; ret = JNI_CreateJavaVM(&jvm,&env,&vm_args); if (ret < 0) { fprintf(stderr, "Can't create Java VM. Error: %ld\n", ret); return(1); } if (argc < 2) { printf("No class specified. Exiting...\n\n"); return(-1); } jstring jstr = env->NewStringUTF(""); jobjectArray str_array = env->NewObjectArray(argc-2, env->FindClass("java/lang/String"), jstr); // Pass main arguments to Java for( i = 2; i < argc; i++ ) { jstr = env->NewStringUTF (argv[i]); if (jstr == 0) { fprintf(stderr, "Out of memory\n"); return(1); } env->SetObjectArrayElement( str_array, i - 2, jstr); } jclass clazz = env->FindClass(dotsToSlashes(argv[1])); if (clazz == 0) { fprintf(stderr, "Can't locate the %s class. Exiting...\n", argv[1]); return(1); } mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V"); if (mid == 0) { fprintf(stderr, "Can't locate the main method. Exiting...\n"); return(1); } env->CallStaticVoidMethod (clazz, mid, str_array); jvm->DestroyJavaVM(); return(0); }