jclass cls = (*env)->FindClass(env,"java/util/Date"); jmethodID constructor_mid = env->GetMethodID(env,cls,"<init>","()V"); jobject date_obj = env->NewObject(env,cls,constructor_mid); <!-- 通知垃圾回收期回收對象 --> (*env)->DeleteLocalRef(env,data_obj);
char* c_str = "迪麗熱巴"; jclass str_cls = (*env)->FindClass(env,"Ljava/langString;"); jmethodID constructor_mid = (*env)->GetMethodID(env,str_cls,"<init>","([BLjava/lang/String;])V") <!-- 第一個參數 --> <!-- jbyte -> char --> jbyteArray bytes = (*env)->NewByteArray(env,strlen(c_str)); <!-- byte 數組賦值 --> (*env)->SetByteArrayRegion(env,bytes,0,strlen(c_str),c_str); <!-- 第二個參數 --> jstring charsetName = (*env)->NewStringUTF(env,"GB2312"); return (*env)->NewObject(env,str_cls,constructor_mid,bytes,charsetName);
#include <stdlib.h> int compare(const void* a,const void* b){ return (*a) -(*b); } <!-- 對java傳遞過來的數組進行排序 --> <!-- NULL 操做的是同一塊內存 : 第三個參數是一個jboolean類型的指針,若是被賦值爲1,表示內部進行了拷貝,爲零表示內部沒有拷貝,是同一塊內存。程序員沒法控制這個變量 --> jint * elems = (*eng)->GetIntArrayElements(env,arr,NULL); <!-- 數組的長度,env --> int len = (*eng)->GetArrayLength(env,arr); <!-- 函數指針 --> <!-- 排序 --> qsort(elems,len,sizeof(jint),compare); <!-- jni 數據同步 --> <!-- 第四個參數 mode 0,java數組進行更新,而且釋放C/C++數組 JNI_ABORT,java 數組不進行更新,可是釋放C/C++數組 JNI_COMMIT,java數組進行更新,不釋放C/C++數組(函數運行完,數組仍是要釋放的) --> (*env)->ReleaseIntArrayElements(env,arr,elems,0);
jintArray jint_arr = (*env)->NewInntArray(env,len) jint* elems = (*env)->GetIntArrayElements(env,jint_arr,NULL); for(int i=0;i<len;++i){ elems[i] = i; } (*env)->ReleaseIntArrayElements(env,jint_arr,elems,0); return jint_arr;
#一、訪問一個很大的java對象,使用完以後,還要進行復雜的耗時操做
#二、建立了大量的局部引用,佔用了太多的內存,並且這些局部引用跟後面的操做沒有關聯。java
<!-- 解決數據共享問題(能夠跨多個線程),手動控制內存的使用 -->
<!-- 本身處理線程安全問題 -->程序員
jstring global_str; void createGlobalRef(){ jstring obj = (*env)->NewStringUTF(env,"jni is powerful"); global_str = (*env)->NewGlobalRef(obj); } void getGlobalRef(){ return global_str; } void deleteGlobalRef(){ (*env)->DeleteGlobalRef(global_str); }
<!-- java 方法 --> class JniTest{ public native void createGlobalRef(); public native void getGlobalRef(); public native void deleteGlobalRef(); public static void main(String[] args){ JniTest t = new JniTest(); t.createGlobalRef(); t.getGlobalRef(); t.deleteGlobalRef(); t.getGlobalRef(); } }
<!-- 節省內存,在內存不足時能夠是釋放所引用的對象 -->
<!-- 能夠引用一個不經常使用的對象,若是爲NULL,臨時建立 -->
<!-- 建立: NewWeakGlobalRef,銷燬 DeleteGlboalWeakRef -->數組
<!--1、 保證java代碼能夠運行 --> <!--2、 確保補救措施,保證C代碼繼續運行--> <!--JNI 本身拋出的異常,在Java層沒法被捕捉,只能在C層清空--> <!--用戶本身拋出的異常,能夠在Java層處理 --> void exception(JNIEnv* env,jobject obj){ jclass cls = (*env)->GetObjectClass(env,obj); jfieldId fid = (*env)->GetFieldID(env,cls,"key2","Ljava/lang/String;"); <!-- 檢測是否發生Java異常 --> jthrowable exception = (*env)->ExceptionOccurred(env); if(exception != null){ <!-- 讓Java 代碼能夠繼續執行 --> <!-- 清空異常信息 --> (*env)->ExceptionClear(env); <!-- 補救措施 --> <!-- 獲取第二個屬性 確保必須能夠獲得--> fid = (*env)->GetFieldID(env,cls,"key","Ljava/lang/String;"); } jstring jstr = (*env)->GetObjectField(env,jobj,fid); char * str = (*env)->GetStringUTFChars(env,jstr,NULL); <!-- 對比屬性值是否合法 --> if(stricmp(str,"super jason1") != 0){ <!-- 認爲拋出異常,給Java層處理 --> jclass newExeCls = (*env)->FindClass(env,"Ljava/lang/IllegalArgumentException;"); (*env)->ThrowNew(env,newExeCls,"Key's value is invalid!"); } }
java 代碼緩存
t.exception();
<!-- 在Java層循環調用不少次 一個native方法 --> void cached(JNIEnv* env,jobject obj){ jclass cls = (*env)->GetObjectClass(env,obj); <!-- 獲取fid 只獲取一次 --> <!-- 局部靜態變量 ; --> static jfieldID = key_id = null; if(key_id == null){ key_id = (*env)->GetFieldID(env,cls,"key","Ljava/lang/String;"); print("==========GetFieldID=========="); } }
<!-- 在C層後面使用的對象在一個方法裏面初始化,initIDs()在加載庫的時候調用。 -->
java安全
public static void initIDs(); static { System.load("lib"); initIDs(); }
C :函數
jfieldID key_fid; initIds(JNIEnv* env,jclass jcls){ <!-- jclass cls = (*env)->GetObjectClass(env,obj); --> key_fid = (*env)->GetFieldID(env,jcls,"key","Ljava/lang/String;"); }