通过JNI实现C++与Java双向通信,Java使用native方法声明并由C++实现对应函数,C++通过JNIEnv指针调用Java方法回调,需管理类型转换、内存释放及全局引用,确保跨平台交互稳定。

在跨平台开发中,C++与Java之间的通信是一个常见需求。通过JNI(Java Native Interface),可以实现Java调用C++代码,也可以让C++触发Java方法回调。这种方式广泛应用于Android NDK开发、高性能计算模块集成等场景。
JNI基本原理
JNI是Java提供的标准接口,允许Java代码与本地语言(如C/C++)交互。核心机制是:Java通过native关键字声明方法,由C++实现对应函数,并通过特定命名规则和JNI环境指针进行绑定。
JNIEnv* 是关键参数,它提供了操作Java对象、调用方法、访问字段的能力。所有与Java交互的操作都必须通过JNIEnv指针完成。
Java调用C++函数
实现步骤如下:
立即学习“Java免费学习笔记(深入)”;
- 在Java类中声明native方法:
public native int add(int a, int b); - 使用javac编译后,用javah生成头文件(或使用javac -h),得到类似:
Java_com_example_MathUtil_add(JNIEnv*, jobject, jint, jint); - C++中实现该函数,例如:
extern "C" JNIEXPORT jint JNICALL
Java_com_example_MathUtil_add(JNIEnv* env, jobject thiz, jint a, jint b) {
return a + b;
}
注意extern "C"防止C++名称修饰,确保符号正确导出。
C++调用Java方法(回调)
当需要从C++主动通知Java时,需缓存类引用和方法ID:
采用HttpClient向服务器端action请求数据,当然调用服务器端方法获取数据并不止这一种。WebService也可以为我们提供所需数据,那么什么是webService呢?,它是一种基于SAOP协议的远程调用标准,通过webservice可以将不同操作系统平台,不同语言,不同技术整合到一起。 实现Android与服务器端数据交互,我们在PC机器java客户端中,需要一些库,比如XFire,Axis2,CXF等等来支持访问WebService,但是这些库并不适合我们资源有限的android手机客户端,
- 获取JavaVM指针(可在onLoad中保存)
- 通过AttachCurrentThread获得当前线程的JNIEnv*
- 查找目标类并获取jclass引用
- GetMethodID或GetStaticMethodID获取方法句柄
- 构造参数并调用CallVoidMethod等函数
示例代码片段:
JNIEnv* env;
JavaVM* jvm;
jvm->AttachCurrentThread(&env, nullptr);
jclass cls = env->FindClass("com/example/Callback");
jmethodID mid = env->GetMethodID(cls, "onResult", "(I)V");
env->CallVoidMethod(obj, mid, 42);
数据类型转换与内存管理
JNI提供基本类型映射(如jint对应int),复杂类型需转换:
- 字符串:NewStringUTF / GetStringUTFChars
- 数组:GetIntArrayElements / ReleaseIntArrayElements
- 对象创建:NewObject配合GetMethodID使用构造函数
务必成对使用获取与释放函数,避免内存泄漏或JVM崩溃。
全局引用可用于跨线程持有Java对象:
g_callback_obj = env->NewGlobalRef(obj);
基本上就这些。掌握JNI命名规则、环境获取、类型转换和生命周期管理,就能稳定实现C++与Java的双向通信。










