JNI 调用Java中的super.method()
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类型,返回NULLjclass 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,关注获取第一手资料。
本文完。