jni基础(2)

C调用java
1.访问构造方法
// 注意:使用 javap -s -p java.util.Date 获得签名,
//  代表实例化构造方法

jclass cls = (*env)->FindClass(env, "java/util/Date");
//jmethodID
jmethodID constructor_mid = (*env)->GetMethodID(env, cls, "", "()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);
2.访问父类方法
jclass cls = (*env)->GetObjectClass(env, jobj);
    //获取man属性(对象)
jfieldID fid = (*env)->GetFieldID(env, cls, "human", "Lcom/golf/jni/Human;");
    //获取
jobject human_obj = (*env)->GetObjectField(env, jobj, fid);

    //执行sayHi方法
jclass human_cls = (*env)->FindClass(env, "com/golf/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);

3.中文乱码问题(通过调用java层的String来解决)
       char *c_str = "会乱码的中文";
    //jstring jstr = (*env)->NewStringUTF(env, c_str);
    //执行String(byte bytes[], String charsetName)构造方法需要的条件

    jclass str_cls = (*env)->FindClass(env, "java/lang/String");
    jmethodID constructor_mid = (*env)->GetMethodID(env, str_cls, "", "([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);

    //字符编码jstring
    jstring charsetName = (*env)->NewStringUTF(env, "GB2312");

    //调用构造函数,返回编码之后的jstring
    return (*env)->NewObject(env,str_cls,constructor_mid,bytes,charsetName);
4.排序
JNIEXPORT void JNICALL Java_com_golf_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_golf_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;
}
5.引用及异常处理
//全局引用
global_str = (*env)->NewGlobalRef(env, obj);
//释放
(*env)->DeleteGlobalRef(env, global_str);

//局部引用
jobject obj = (*env)->NewObject(env, cls, constructor_mid);
(*env)->DeleteLocalRef(env, obj);

//异常处理
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);

     //抛出异常给Java层处理
    jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
    (*env)->ThrowNew(env,newExcCls,"key's value is invalid!");

}

你可能感兴趣的:(jni基础(2))