夜雨JC

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1、访问构造方法

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

2、访问父类的构造方法

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

 

3、数组处理_JNI引用 数组排序 int[] arr

1、函数指针:

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

 

2、返回一个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;

 

3、局部引用和全局引用

1、局部引用,通过DeleteLocalRef手动释放对象

#1、访问一个很大的java对象,使用完之后,还要进行复杂的耗时操作
#2、创建了大量的局部引用,占用了太多的内存,而且这些局部引用跟后面的操作没有关联。

2、全局引用,多个方法里面都可以引用

<!-- 解决数据共享问题(可以跨多个线程),手动控制内存的使用 -->
<!-- 自己处理线程安全问题 -->

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

 

3、弱全局引用

<!-- 节省内存,在内存不足时可以是释放所引用的对象 -->
<!-- 可以引用一个不常用的对象,如果为NULL,临时创建 -->
<!-- 创建: NewWeakGlobalRef,销毁 DeleteGlboalWeakRef -->

4、异常处理 (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();

 

4、缓存策略

1、使用局部静态变量

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

}        

 

2、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;");
}

 

posted on 2019-06-13 20:26  夜雨JC  阅读(199)  评论(0编辑  收藏  举报