Android Studio JNI学习之(2)-JAVA与原生代码通信

前言


       在上一篇文章中已经介绍了JNI入门,并且演示了Java通过调用原生方法打印Hello Jni,下面介绍原生代码是如何访问Java的属性和方法。


正文

  •      访问域

          Java有两类域:实例域和静态域。类实例属于自己的实例域,而类共享同一个静态域。

         拥有两种域的Java

  

public class JavaClass {
    private String instanceField = "Instance Field";
    private static String staticField = "Static Field";
    ...
}

       访问实例域代码

JNIEXPORT jstring JNICALL Java_com_study_eric_jni_JniTest_getStringFromJavaField
        (JNIEnv *env, jobject object, jobject jobject1) {
    jclass clazz = (*env)->GetObjectClass(env, jobject1); // 先获取到对象的类
    jfieldID jfieldID = (*env)->GetFieldID(env, clazz, "instanceField", "Ljava/lang/String;"); // 获取实例域ID
    return (*env)->GetObjectField(env, jobject1, jfieldID);
}     

     调用原生方法是把JavaClass类实例传入

textView.setText(jni.getStringFromJavaField(new JavaClass()));

     同理访问静态域提供了GetStaticFieldID、GetStaticObjectField方法,在这就演示了。

     -- GetFieldID、GetStaticFieldID方法参数"Ljava/lang/String;"说明

        "Ljava/lang/String;"是方法描述符,方法描述符可以通过Java类型签名映射获得



        Java的String类型就是对于签名Ljava/lang/String;

       介绍另一种方法使用命令javap获取签名

     

 

 


  •      访问方法

         访问实例方法代码
   
JNIEXPORT jstring JNICALL Java_com_study_eric_jni_JniTest_getStringFromJavaInstance
        (JNIEnv *env, jobject object, jobject jobject1) {
    jclass clazz = (*env)->GetObjectClass(env, jobject1);
    jmethodID jmethodID = (*env)->GetMethodID(env, clazz, "instanceMethod", "()Ljava/lang/String;");
    return (*env)->CallObjectMethod(env, jobject1, jmethodID);
}

       访问静态方法提供了GetStaticMethodID、CallStaticObjectMethod

  •      异常处理

       异常处理是Java的重要功能,JNI中异常行为与Java有所不同,JNI要求开放人员在异常发生后显式地实现异常处理流。

       Java类抛出异常

/**
     * 抛出异常方法
     */
    private void throwingMethod() throws NullPointerException {
        throw  new NullPointerException("Null pointer");
    }

    原生代码中异常处理

JNIEXPORT jstring JNICALL Java_com_study_eric_jni_JniTest_getStringFromJavaThrowing
        (JNIEnv *env, jobject object, jobject jobject1) {
    jclass clazz = (*env)->GetObjectClass(env, jobject1);
    jmethodID jmethodID = (*env)->GetMethodID(env, clazz, "throwingMethod", "()V");
    (*env)->CallNonvirtualVoidMethod(env, jobject1, clazz, jmethodID);
    jthrowable ex;
    ex = (*env)->ExceptionOccurred(env);
    if (ex != 0) {
        (*env)->ExceptionClear(env);
        return (*env)->NewStringUTF(env, "null pointer");
    } else {
        return (*env)->NewStringUTF(env, "success");
    }
}

    JNI抛出异常

JNIEXPORT void JNICALL Java_com_study_eric_jni_JniTest_getFromJniThrowing
        (JNIEnv *env, jobject object) {
    jclass clazz = (*env)->FindClass(env, "java/lang/NullPointerException");
    if (clazz != 0) {
        (*env)->ThrowNew(env, clazz, "Exception message.");
    }
}




发布了18 篇原创文章 · 获赞 10 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/LIANGJIANGLI/article/details/72846396