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;");
}
相关文章
相关标签/搜索