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