💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
### 14.4 JNI调用Java方法的流程 JNI调用Java方法的流程是先通过类名找到类,然后再根据方法名找到方法的id,最后就可以调用这个方法了。如果是调用Java中的非静态方法,那么需要构造出类的对象后才能调用它。下面的例子演示了如何在JNI中调用Java的静态方法,至于调用非静态方法只是多了一步构造对象的过程,这里就不再介绍了。 首先需要在Java中定义一个静态方法供JNI调用,如下所示。 public static void methodCalledByJni(String msgFromJni) { Log.d(TAG, "methodCalledByJni, msg: " + msgFromJni); } 然后在JNI中调用上面定义的静态方法: void callJavaMethod(JNIEnv *env, jobject thiz) { jclass clazz = env->FindClass("com/ryg/JniTestApp/MainActivity"); if (clazz == NULL) { printf("find class MainActivity error! "); return; } jmethodID id = env->GetStaticMethodID(clazz, "methodCalledByJni", "(Ljava/lang/String; )V"); if (id == NULL) { printf("find method methodCalledByJni error! "); } jstring msg = env->NewStringUTF("msg send by callJavaMethod in test.cpp."); env->CallStaticVoidMethod(clazz, id, msg); } 从callJavaMethod的实现可以看出,程序首先根据类名com/ryg/JniTestApp/MainActivity找到类,然后再根据方法名methodCalledByJni找到方法,其中(Ljava/lang/String; )V是methodCalledByJni方法的签名,接着再通过JNIEnv对象的CallStaticVoidMethod方法来完成最终的调用过程。 最后在Java_com_ryg_JniTestApp_MainActivity_get方法中调用callJavaMethod方法,如下所示。 jstring Java_com_ryg_JniTestApp_MainActivity_get(JNIEnv *env, jobject thiz){ printf("invoke get in c++\n"); callJavaMethod(env, thiz); return env->NewStringUTF("Hello from JNI in libjni-test.so ! "); } 由于MainActivity会调用JNI中的Java_com_ryg_JniTestApp_MainActivity_get方法,Java_com_ryg_JniTestApp_MainActivity_get方法又会调用callJavaMethod方法,而callJavaMethod方法又会反过来调用MainActivity的methodCalledByJni方法,这样一来就完成了一次从Java调用JNI然后再从JNI中调用Java方法的过程。安装运行程序,可以看到如下日志,这说明程序已经成功地从JNI中调用了Java中的methodCalledByJni方法。 D/MainActivity: methodCalledByJni, msg: msg send by callJavaMethod in test.cpp. 我们可以发现,JNI调用Java的过程和Java中方法的定义有很大关联,针对不同类型的Java方法,JNIEnv提供了不同的接口去调用,本章作为一个JNI的入门章节就不再对它们一一进行介绍了,毕竟大部分应用层的开发人员并不需要那么深入地了解JNI,如果读者感兴趣可以自行阅读相关的JNI专业书籍。