JNI学习(1)

来源:互联网 发布:如何做网络写手 编辑:程序博客网 时间:2024/06/08 16:36

use the JNI if your Java application must interoperate with native codethat resides in the same process.

static {

System.loadLibrary("HelloWorld");

}

the static initializer is run before invoking any methods in the HelloWorldclass, thus ensuring that the native library is loaded before the print nativemethod is called.


1.1.1 JNIEnvinterface pointer

the JNIEnv interface pointer, points to a location that contains a pointerto a function table. Each entry in the function table points to a JNI function.



The second argument jobject to an instance native method is a reference tothe object on which the method is invoked, similar to the this pointer in C++.while to a static native method is a reference to the class in which the methodis defined.

1.1.2 JNIAccessing Strings

The JNI treats primitive types and reference types differently. The mappingof primitive types is straightforward.

The jstring type represents strings in the Java virtual machine, and isdifferent from the regular C string type (a pointer to characters, char *). Youcannot use a jstring as a normal C string.



1.2.1 AccessingFields

Accessing an Instance Field

First, it calls GetFieldID to obtain the field IDfrom the class reference, field name, and field descriptor:

fid = (*env)->GetFieldID(env, cls, "s","Ljava/lang/String;");

pass the object reference and the field ID to theappropriate instance field access function:

jstr = (*env)->GetObjectField(env, obj, fid);

the JNI also supports other functions such asGetIntField and SetFloatField for accessing instance fields of primitive types.

JNI field descriptors:

int "I",float "F",double "D",boolean"Z".

java.lang.String "Ljava/lang/String;"

"[" for the descriptor of the type of array.

jclass intArrCls = (*env)->FindClass(env, "[I");

The "[I" argument to FindClass is the JNI class descriptor thatcorresponds to the int[] type.

javap tool to generate the field descriptors fromclass files:

javap -s -p InstanceFieldAccess

Accessing Static Fields:

two differencesbetween accessing a static field and an instance field:

1. You callGetStaticFieldID for static fields, as opposed to GetFieldID for

instance fields.GetStaticFieldID and GetFieldID have the same return type

jfieldID.

2. Once you haveobtained the static field ID, you pass the class reference,as

opposed to an objectreference, to the appropriate static field access function.

1.2.2 CallingMethods:

Calling Instance Methods:

1.jmethodID mid=(*env)->GetMethodID(env, cls, "callback", "()V");

2.(*env)->CallVoidMethod(env,obj, mid);

Call<Type>Methodfamily of functions to invoke interface methods as well.

Method Descriptor:

"(I)V"denotes a method that takes one argument of type int and has return type void.

"()D"denotes a method that takes no arguments and returns a double.

Calling Static Methods:

GetStaticMethodID,CallStaticVoidMethod

Calling InstanceMethods of a Superclass:

CallNonvirtualVoidMethod


1.3.1 InvokingConstructors

NewObject

/* Get the method IDfor the String(char[]) constructor */

cid =(*env)->GetMethodID(env, stringClass,

                             "<init>", "([C)V");

/* Construct ajava.lang.String object */

result =(*env)->NewObject(env, stringClass, cid, elemArr);

AllocObject

result =(*env)->AllocObject(env, stringClass);

if (result) {

   (*env)->CallNonvirtualVoidMethod(env, result, stringClass,

                                    cid, elemArr);

1.3.2 CachingField and Method IDs

Caching at the Point of Use

static jfieldIDfid_s = NULL; /* cached field ID for s */

if (fid_s == NULL) {/*check whether it is cached*/

   fid_s= (*env)->GetFieldID(env, cls, "s",

       "Ljava/lang/String;");

   if(fid_s == NULL) {

         return; /* exception already thrown */

       }

    }

Caching in the Defining Class’s Initializer

private staticnative void initIDs();

static {

       System.loadLibrary("InstanceMethodCall");

       initIDs();

  }

Comparison between the Two Approaches toCaching IDs

Caching at the pointof use has a number of disadvantages :

1.caching at thepoint of use requires a check in the execution fast path and may also requireduplicated checks。

2.Method and fieldIDs are only valid until the class is unloaded.


1.4.1 Localand Global References

Local References

All local referencescreated during the execution of a native method will be freed once the nativemethod returns.

In addition,programmers may explicitly manage the lifetime of local references using JNIfunctions such as DeleteLocalRef.

Local references arealso only valid in the thread that creates them

Global References

You can use a globalreference across multiple invocations of a native method. A global referencecan be used across multiple threads and remains valid until it is freed by theprogrammer.

Unlike localreferences, which are created by most JNI functions, global references arecreated by just one JNI function, NewGlobalRef.

  if(stringClass == NULL) {

     jclass localRefCls =

         (*env)->FindClass(env, "java/lang/String");

     if (localRefCls == NULL) {

         return NULL; /* exception thrown */

     }

     /* Create a global reference */

     stringClass = (*env)->NewGlobalRef(env,localRefCls);

     /* The local reference is no longer useful */

     (*env)->DeleteLocalRef(env, localRefCls);

     /* Is the global reference created successfully? */

     if (stringClass == NULL) {

         return NULL; /* out of memory exception thrown */

     }

  }

Weak Global References

Weak globalreferences are new in Java 2 SDK release 1.2. They are created using NewGlobalWeakRef andfreed using DeleteGlobalWeakRef.Like global references, weak global references remain valid across nativemethod calls and across different threads. Unlike global references, weakglobal references do not keep the underlying object from being garbagecollected.

You can use IsSameObject to determinewhether a non- NULL weak global reference still points to a live object.Suppose wobj is a non-NULL weak global reference. The following call:

(*env)->IsSameObject(env,wobj, NULL),returns JNI_TRUE if wobj refers to an object that has already beencollected, and returns JNI_FALSE if wobj still refers to a live object.

原创粉丝点击