阅读 146

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 RoutinesNativeType
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,关注获取第一手资料。

本文完。


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐