JNI 调用Java中的super.method()
在上一篇中介绍了JNI 回调实例方法与静态方法。本文是JNI系列的第八篇,介绍JNI中的如何在Native代码
中调用当前类的父类的方法。
系列文章的大纲如下:
- JNI 简介
- JNI 基本类型
- JNI String
- JNI 数组
- JNI 实例变量
- JNI 静态变量
- JNI 回调实例方法与静态方法
- JNI 调用Java中的super.method()
- JNI 中创建对象
- JNI 中创建对象数组
- JNI 中局部引用和全局引用
- JNI 动态注册
- 使用Android NDK编译Android的Native库
JNI 调用Java中的super.method()
如果我们需要在JNI中调用一个对象的父类的方法,怎么来实现呢?
JNI为我们提供了这样的入口,一起来看一下吧。
获取父类:
// 如果clazz是除了jclass这个类型之外的对象,返回clazz的父类;
// 如果clazz是jclass类型的对象,或者是interface类型,返回NULL
jclass GetSuperclass(JNIEnv *env, jclass clazz);
调用super类的方法:
// 调用对象obj的父类clazz的方法ID为methodID的方法
NativeType CallNonvirtual<type>Method(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
NativeType CallNonvirtual<type>MethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue *args);
NativeType CallNonvirtual<type>MethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args);
其中:
CallNonvirtual<type>Method Routines |
NativeType |
---|---|
CallNonvirtualVoidMethod() |
jobject |
CallNonvirtualObjectMethod() |
jobject |
CallNonvirtualBooleanMethod() |
jboolean |
CallNonvirtualByteMethod() |
jbyte |
CallNonvirtualCharMethod() |
jchar |
CallNonvirtualShortMethod() |
jshort |
CallNonvirtualIntMethod() |
jint |
CallNonvirtualLongMethod() |
jlong |
CallNonvirtualFloatMethod() |
jfloat |
CallNonvirtualDoubleMethod() |
jdouble |
CallNonvirtual<type>Method()
、CallNonvirtual<type>MethodA()
和CallNonvirtual<type>MethodV()
之前的区别在于传递参数的形式上的区别。
具体参见下面的实例。
通过下面的实例来加深一下理解。
实例
我们来看一个实例。
这次依然使用一个新文件来说明:
package myjni.nonvirtual;
class A {
public void doSomething() {
System.out.println("A.doSomething " + this.getClass().getName());
}
}
class B extends A {
public void doSomething() {
System.out.println("B.doSomething " + this.getClass().getName());
}
}
public class Test {
static {
System.loadLibrary("hello");
}
public static native void jniTest(B b);
public static void main(String[] args) {
B obj = new B();
jniTest(obj);
}
}
如果还不清楚如果生成头文件请参考JNI简介。
类B继承类A,在类B中重写方法doSomething
。测试的方法是jniTest
传递类型B的对象,我们使用它去调用其父类的方法doSomething
。
生成头文件myjni_nonvirtual_Test.h
的签名为:
/*
* Class: myjni_nonvirtual_Test
* Method: jniTest
* Signature: (Lmyjni/nonvirtual/B;)V
*/
JNIEXPORT void JNICALL Java_myjni_nonvirtual_Test_jniTest
(JNIEnv *, jclass, jobject);
实现函数Java_myjni_nonvirtual_Test_jniTest
:
JNIEXPORT void JNICALL Java_myjni_nonvirtual_Test_jniTest(JNIEnv *env, jclass clazz, jobject obj) {
// Call obj.doSomething()
jclass bClazz = env->GetObjectClass(obj);
if (bClazz == nullptr) {
std::cout << "get obj class failed\n";
return;
}
jmethodID midDoSomething = env->GetMethodID(bClazz, "doSomething", "()V");
if (midDoSomething == nullptr) {
std::cout << "get method failed\n";
return;
}
env->CallVoidMethod(obj, midDoSomething);
// Call obj.super().doSomething()
jclass parentClass = env->GetSuperclass(bClazz);
if (parentClass == nullptr) {
std::cout << "get super class failed\n";
return;
}
jmethodID midDoSomethingInParent = env->GetMethodID(parentClass, "doSomething", "()V");
if (midDoSomethingInParent == nullptr) {
std::cout << "get method failed\n";
return;
}
env->CallNonvirtualVoidMethod(obj, parentClass, midDoSomethingInParent);
}
编译生成动态库,并运行Java程序得到输出:
B.doSomething myjni.nonvirtual.B
A.doSomething myjni.nonvirtual.B
vx搜:极客Furzoom,关注获取第一手资料。
本文完。