jni字符串乱码,异常,引用....

来源:互联网 发布:长春办公软件培训 编辑:程序博客网 时间:2024/06/15 10:15
//访问构造方法//使用java.util.Date产生一个当前的时间戳JNIEXPORT jobject JNICALL Java_com_dongnaoedu_jni_JniTest_accessConstructor(JNIEnv *env, jobject jobj){jclass cls = (*env)->FindClass(env, "java/util/Date");//jmethodIDjmethodID constructor_mid = (*env)->GetMethodID(env, cls, "<init>", "()V");//实例化一个Date对象jobject date_obj = (*env)->NewObject(env, cls, constructor_mid);//调用getTime方法jmethodID mid = (*env)->GetMethodID(env, cls, "getTime", "()J");jlong time = (*env)->CallLongMethod(env, date_obj, mid);printf("\ntime:%lld\n",time);return date_obj;}//调用父类的方法JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_accessNonvirtualMethod(JNIEnv *env, jobject jobj){jclass cls = (*env)->GetObjectClass(env, jobj);//获取man属性(对象)jfieldID fid = (*env)->GetFieldID(env, cls, "human", "Lcom/dongnaoedu/jni/Human;");//获取jobject human_obj = (*env)->GetObjectField(env, jobj, fid);//执行sayHi方法jclass human_cls = (*env)->FindClass(env, "com/dongnaoedu/jni/Human"); //注意:传父类的名称jmethodID mid = (*env)->GetMethodID(env, human_cls, "sayHi", "()V");//执行//(*env)->CallObjectMethod(env, human_obj, mid);//调用的父类的方法(*env)->CallNonvirtualObjectMethod(env, human_obj, human_cls, mid);}//中文问题JNIEXPORT jstring JNICALL Java_com_dongnaoedu_jni_JniTest_chineseChars(JNIEnv *env, jobject jobj, jstring in){//输出//char *c_str = (*env)->GetStringUTFChars(env, in, JNI_FALSE);//printf("%s\n",c_str);//c -> jstringchar *c_str = "马蓉与宋江";//char c_str[] = "马蓉与宋喆";//jstring jstr = (*env)->NewStringUTF(env, c_str);//执行String(byte bytes[], String charsetName)构造方法需要的条件//1.jmethodID//2.byte数组//3.字符编码jstringjclass str_cls = (*env)->FindClass(env, "java/lang/String");jmethodID constructor_mid = (*env)->GetMethodID(env, str_cls, "<init>", "([BLjava/lang/String;)V");//jbyte -> char //jbyteArray -> char[]jbyteArray bytes = (*env)->NewByteArray(env, strlen(c_str));//byte数组赋值//0->strlen(c_str),从头到尾//对等于,从c_str这个字符数组,复制到bytes这个字符数组(*env)->SetByteArrayRegion(env, bytes, 0, strlen(c_str), c_str);//字符编码jstringjstring charsetName = (*env)->NewStringUTF(env, "GB2312");//调用构造函数,返回编码之后的jstringreturn (*env)->NewObject(env,str_cls,constructor_mid,bytes,charsetName);}int compare(int *a,int *b){return (*a) - (*b);}//传入JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_giveArray(JNIEnv *env, jobject jobj, jintArray arr){//jintArray -> jint指针 -> c int 数组jint *elems = (*env)->GetIntArrayElements(env, arr, NULL);//printf("%#x,%#x\n", &elems, &arr);//数组的长度int len = (*env)->GetArrayLength(env, arr);//排序qsort(elems, len, sizeof(jint), compare);//同步//mode//0, Java数组进行更新,并且释放C/C++数组//JNI_ABORT, Java数组不进行更新,但是释放C/C++数组//JNI_COMMIT,Java数组进行更新,不释放C/C++数组(函数执行完,数组还是会释放)(*env)->ReleaseIntArrayElements(env, arr, elems, JNI_COMMIT);}//返回数组JNIEXPORT jintArray JNICALL Java_com_dongnaoedu_jni_JniTest_getArray(JNIEnv *env, jobject jobj, jint len){//创建一个指定大小的数组jintArray jint_arr = (*env)->NewIntArray(env, len);jint *elems = (*env)->GetIntArrayElements(env, jint_arr, NULL);int i = 0;for (; i < len; i++){elems[i] = i;}//同步(*env)->ReleaseIntArrayElements(env, jint_arr, elems, 0);return jint_arr;}//JNI 引用变量//引用类型:局部引用和全局引用//作用:在JNI中告知虚拟机何时回收一个JNI变量//局部引用,通过DeleteLocalRef手动释放对象//1.访问一个很大的java对象,使用完之后,还要进行复杂的耗时操作//2.创建了大量的局部引用,占用了太多的内存,而且这些局部引用跟后面的操作没有关联性//模拟:循环创建数组JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_localRef(JNIEnv *env, jobject jobj){int i = 0;for (; i < 5; i++){//创建Date对象jclass cls = (*env)->FindClass(env, "java/util/Date");jmethodID constructor_mid = (*env)->GetMethodID(env, cls, "<init>", "()V");jobject obj = (*env)->NewObject(env, cls, constructor_mid);//此处省略一百行代码...//不在使用jobject对象了//通知垃圾回收器回收这些对象(*env)->DeleteLocalRef(env, obj);//此处省略一百行代码...}}//全局引用//共享(可以跨多个线程),手动控制内存使用jstring global_str;//创建JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_createGlobalRef(JNIEnv *env, jobject jobj){jstring obj = (*env)->NewStringUTF(env, "jni development is powerful!");global_str = (*env)->NewGlobalRef(env, obj);}//获得JNIEXPORT jstring JNICALL Java_com_dongnaoedu_jni_JniTest_getGlobalRef(JNIEnv *env, jobject jobj){return global_str;}//释放JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_deleteGlobalRef(JNIEnv *env, jobject jobj){(*env)->DeleteGlobalRef(env, global_str);}//弱全局引用//节省内存,在内存不足时可以是释放所引用的对象//可以引用一个不常用的对象,如果为NULL,临时创建//创建:NewWeakGlobalRef,销毁:DeleteGlobalWeakRef//异常处理//1.保证Java代码可以运行//2.补救措施保证C代码继续运行//JNI自己抛出的Throwable异常,在Java层被相应异常catch捕捉,还能在C层清空//用户通过ThrowNew抛出的异常,可以在Java层捕捉JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_exeception(JNIEnv *env, jobject jobj){jclass cls = (*env)->GetObjectClass(env, jobj);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 jason") != 0){//认为抛出异常,给Java层处理jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");(*env)->ThrowNew(env,newExcCls,"key's value is invalid!");}}//缓存策略//static jfieldID key_id JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_cached(JNIEnv *env, jobject jobj){jclass cls = (*env)->GetObjectClass(env, jobj);//获取jfieldID只获取一次//局部静态变量static jfieldID key_id = NULL;if (key_id == NULL){key_id = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");printf("--------GetFieldID-------\n");}}//初始化全局变量,动态库加载完成之后,立刻缓存起来jfieldID key_fid;jmethodID random_mid;JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_initIds(JNIEnv *env, jclass jcls){key_fid = (*env)->GetFieldID(env, jcls, "key", "Ljava/lang/String;");random_mid = (*env)->GetMethodID(env, jcls, "genRandomInt", "(I)I");}

访问构造方法和访问普通方法的一个区别是其中的一个参数是<init>,从jni层向java层返回中文字符串会出现乱码,所以要改变编码为GB2312,要改变java层的字符串,需要在jni层改变厚同步才能在java层收到变化。java层native代码

public class JniTest {public String key = "jason";public Human human = new Man(); public static int count = 9;public native static String getStringFromC();public native String getString2FromC(int i);//访问属性,返回修改之后的属性内容public native String accessField();public native void accessStaticField();public native void accessMethod();public native void accessStaticMethod();public native Date accessConstructor();public native void accessNonvirtualMethod();public native String chineseChars(String in);public native void giveArray(int[] array);public native int[] getArray(int len);public native void localRef();public native void createGlobalRef();public native String getGlobalRef();public native void deleteGlobalRef();public native void exeception();public native void cached();public native static void initIds();public static void main(String[] args) {String text = getStringFromC();System.out.println(text);JniTest t = new JniTest();text = t.getString2FromC(6);System.out.println(text);System.out.println("key修改前:"+t.key);t.accessField();System.out.println("key修改后:"+t.key);System.out.println("count修改前:"+count);t.accessStaticField();System.out.println("count修改后:"+count);t.accessMethod();t.accessStaticMethod();t.accessConstructor();t.accessNonvirtualMethod();System.out.println(t.chineseChars("宋喆"));int[] array = {9,100,10,37,5,10};//排序t.giveArray(array);for (int i : array) {System.out.println(i);}//----------int[] array2 = t.getArray(10);System.out.println("------------");for (int i : array2) {System.out.println(i);}System.out.println("------08-17------");t.createGlobalRef();System.out.println(t.getGlobalRef());//用完之后释放t.deleteGlobalRef();System.out.println("释放完了...");//System.out.println(t.getGlobalRef());try {t.exeception();} catch (Exception e) {System.out.println("发生异常:"+e.getMessage());}System.out.println("--------异常发生之后-------");try {t.exeception();} catch (Exception e) {//e.printStackTrace();System.out.println(e.getMessage());}//不断调用cached方法for (int i = 0; i < 100; i++) {t.cached();}}//产生指定范围的随机数public int genRandomInt(int max){System.out.println("genRandomInt 执行了...");return new Random().nextInt(max); }//产生UUID字符串public static String getUUID(){return UUID.randomUUID().toString();}//加载动态库static{System.loadLibrary("jni_study");initIds();}}