JNI学习(1)

本文详细介绍了如何使用JNI让Java应用与同一进程内的本地代码进行交互,包括JNIEnv接口指针、实例方法调用、静态方法调用、字段访问、构造函数调用等关键概念。同时阐述了本地引用与全局引用的区别,以及缓存字段和方法ID的两种策略。最后,文章解释了Java中本地方法返回值与异常处理机制。

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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值