前言
在上一篇文章中已经介绍了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.");
}
}