简介
-
原生代码 中调用 Java 方法也被称为 native回调 。
访问普通方法
简单示例
public class InstanceMethodCall {
static {
System.loadLibrary("InstanceMethodCall");
}
public static void main(String[] args) {
InstanceMethodCall c = new InstanceMethodCall();
c.nativeMethod();
}
private native void nativeMethod();
private void callback() {
System.out.println("In Java");
}
}
JNIEXPORT void JNICALL Java_InstanceMethodCall_nativeMethod(JNIEnv * env, jobject obj) {
// 通过jobject获取jclass
jclass cls = (* env)->GetObjectClass(env, obj);
// 通过jclass获取jmethodID
jmethodID mid = (* env)->GetMethodID(env, cls, "callback", "()V");
if (!mid) {
return;
}
printf("In C\n");
// 通过jobject和jmethodID调用方法
(* env)->CallVoidMethod(env, obj, mid);
}
示例解说
-
GetObjectClass()
:通过jobject
获取jclass
。
-
GetMethodID()
:通过jclass
、 方法名 和 方法描述符 获取jmethodID
。如果没有找到对应方法会抛出NoSuchMethodError
。 方法描述符 的获取方法可以参考 ★06.访问属性 。
-
CallVoidMethod()
:通过jobject
和jmethodID
调用方法。CallVoidMethod()
用于调用返回void
类型的方法。
函数解说
-
GetObjectClass()
:用于获取jclass
。
-
GetMethodID()
:用于获取jmethodID
。
-
Call<Type>Method
:用于调用返回<Type>
类型的方法。
访问静态方法
简单示例
public class StaticMethodCall {
static {
System.loadLibrary("StaticMethodCall");
}
public static void main(String[] args) {
StaticMethodCall c = new StaticMethodCall();
c.nativeMethod();
}
private static void callback() {
System.out.println("In Java");
}
private native void nativeMethod();
}
JNIEXPORT void JNICALL Java_StaticMethodCall_nativeMethod(JNIEnv * env, jobject obj) {
// 通过jobject获取jclass
jclass cls = (* env)->GetObjectClass(env, obj);
// 通过jclass、方法名和方法描述符来获取jmethodID
jmethodID mid = (* env)->GetStaticMethodID(env, cls, "callback", "()V");
if (!mid) {
return;
}
printf("In C\n");
// 通过jclass和jmethodID获取方法
(* env)->CallStaticVoidMethod(env, cls, mid);
}
示例解说
-
GetObjectClass()
:通过jobject
获取jclass
。
-
GetMethodID()
:通过jclass
、 方法名 和 方法描述符 获取jmethodID
。如果没有找到对应方法会抛出NoSuchMethodError
。 方法描述符 的获取方法可以参考 ★06.访问属性 。
-
CallStaticVoidMethod()
:通过jobject
和jmethodID
调用方法。CallVoidMethod()
用于调用返回void
类型的方法。
函数解说
-
GetObjectClass()
:用于获取jclass
。
-
GetMethodID()
:用于获取jmethodID
。
-
CallStatic<Type>Method
:用于调用返回<Type>
类型的静态方法。
调用基类方法
-
CallNonvirtual<Type>Method()
:用于调用基类方法,相当于 Java 代码中的super.fun()
。
调用构造函数
简单示例
jstring MyNewString(JNIEnv * env, jchar * chars, jint len) {
// 通过类型描述符获取jclass
jclass stringClass = (* env)->FindClass(env, "java/lang/String");
if (!stringClass) {
return 0;
}
// 通过jclass、"<init>"和方法描述符获取构造函数的jmethodID
jmethodID cid = (* env)->GetMethodID(env, stringClass, "<init>", "([C)V");
if (!cid) {
return 0;
}
// 创建数组
jcharArray elemArr = (* env)->NewCharArray(env, len);
if (!elemArr) {
return 0;
}
// 设置数组
(* env)->SetCharArrayRegion(env, elemArr, 0, len, chars);
// 通过jclass、构造函数jmethodID和构造函数参数来调用构造函数创建对象
jstring result = (* env)->NewObject(env, stringClass, cid, elemArr);
// 清理
(* env)->DeleteLocalRef(env, elemArr);
(* env)->DeleteLocalRef(env, stringClass);
return result;
}
示例解说
-
FindClass()
:通过 类型描述符 获取对应的jclass
-
GetMethodID()
:通过jclass
、"<init>"
和 方法描述符 获取构造函数的jmethodID
。
-
NewObject()
:通过jclass
、构造函数jmethodID
和构造函数 参数 来调用构造函数创建对象。
函数解说
-
FindClass()
:通过 类型描述符 获取对应的jclass
。
-
GetMethodID()
:通过jclass
、"<init>"
和 方法描述符 获取构造函数的jmethodID
。
-
NewObject()
:通过jclass
、构造函数jmethodID
和构造函数 参数 来调用构造函数创建对象。
注意事项
- 我们可以通过
NewObject()
调用构造函数来构造一个String
,但是 JNI 仍然内置NewString()
,因为内置版本更高效。