ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

JNI 调用Java中的super.method()

2021-11-21 11:02:04  阅读:228  来源: 互联网

标签:Java doSomething super clazz nonvirtual obj JNI jclass


JNI 调用Java中的super.method()

在上一篇中介绍了JNI 回调实例方法与静态方法。本文是JNI系列的第八篇,介绍JNI中的如何在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 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,关注获取第一手资料。

本文完。

标签:Java,doSomething,super,clazz,nonvirtual,obj,JNI,jclass
来源: https://blog.csdn.net/himayan46/article/details/121432243

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有