JNI 學習筆記

一、訪問構造方法

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);

 

三、數組處理_JNI引用 數組排序 int[] arr

一、函數指針:

#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);

 

二、返回一個int類型的數組

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;

 

三、局部引用和全局引用

一、局部引用,經過DeleteLocalRef手動釋放對象

#一、訪問一個很大的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 -->數組

四、異常處理 (Native 異常,沒法在Java層catch) 只能在native 層處理

<!--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==========");
    }

}        

 

二、initIDs(),

<!-- 在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;");
}
相關文章
相關標籤/搜索