C++如何通过JNI调用Java方法?(代码示例)

2次阅读

c++通过 JNI 调用 java 方法需先获取 JNIEnv,再通过 GetObjectClass/FindClass、GetMethodID/GetStaticMethodID、CallObjectMethod/CallStaticObjectMethod 等完成调用,严格处理签名、异常检查及局部引用释放。

C++ 如何通过 JNI 调用 Java 方法?(代码示例)

在 C ++ 中通过 JNI 调用 Java 方法,核心是获取 Java对象 或类的引用,再通过 JNIEnv 提供的函数(如 GetMethodIDCallObjectMethod 等)完成调用。关键在于正确获取类、方法 ID 和参数处理,尤其注意局部 / 全局引用管理和异常检查。

获取 JNIEnv指针 jvm环境

Native 代码必须运行在 JVM 已启动的上下文中。常见方式有:

  • 从 Java 层回调进入 C ++(如声明 native 方法),此时 JNIEnv 由 JVM 自动传入,可直接使用;
  • 在独立 C ++ 程序中主动 Attach 到 JVM(需持有 JavaVM* 指针),调用 GetEnvAttachCurrentThread获取 JNIEnv;
  • Detach 前必须调用 DetachCurrentThread(仅对 Attach 过的 线程)。

调用 Java 实例方法(非静态)

假设 java 类com.example.Utils,含方法public String format(String s, int n),且已有该类实例jobject obj

// 1. 获取类引用(可缓存)jclass cls = env->GetObjectClass(obj); if (!cls) {/* 处理异常 */} <p>// 2. 获取方法 ID(签名需严格匹配)// "format" 是方法名;"(Ljava/lang/String;I)Ljava/lang/String;" 是签名 jmethodID mid = env->GetMethodID(cls, "format", "(Ljava/lang/String;I)Ljava/lang/String;"); if (!mid) {/<em> 方法未找到或异常 </em>/}</p><p>// 3. 构造参数:创建 Java 字符串 jstring jstr = env->NewStringUTF("hello"); if (!jstr) {/<em> 内存不足 </em>/}</p><p>// 4. 调用方法 jstring result = (jstring)env->CallObjectMethod(obj, mid, jstr, 123);</p><p>// 5. 使用结果(如转为 C 字符串)const char* cstr = env->GetStringUTFChars(result, nullptr); if (cstr) {printf("Result: %sn", cstr); env->ReleaseStringUTFChars(result, cstr); // 必须释放 }</p><p>// 6. 清理局部引用(避免引用泄漏)env->DeleteLocalRef(jstr); env->DeleteLocalRef(result); env->DeleteLocalRef(cls);

调用 Java 静态方法

无需 Java 对象实例,改用 GetStaticMethodIDCallStaticXXXMethod

立即学习Java 免费学习笔记(深入)”;

// 获取类(通过类名查找)jclass cls = env->FindClass("com/example/Utils"); if (!cls) {/* 类未找到 */} <p>jmethodID mid = env->GetStaticMethodID(cls, "getVersion", "()Ljava/lang/String;"); if (!mid) {/<em> 异常已抛出 </em>/}</p><p>jstring version = (jstring)env->CallStaticObjectMethod(cls, mid);</p><p>// 后续同上:使用、释放、清理 const char* ver = env->GetStringUTFChars(version, nullptr); if (ver) {printf("Version: %sn", ver); env->ReleaseStringUTFChars(version, ver); } env->DeleteLocalRef(version); env->DeleteLocalRef(cls);

签名生成与常见类型映射

JNI 方法签名决定参数和返回 值类型 ,可用javap -s 查看。常用规则:

  • 基本类型:I(int)、ZBoolean)、Ddouble)等;
  • 对象类型:以 L 开头,全限定名用 / 分隔,结尾加;,如Ljava/lang/String;
  • 数组:前置 [,如[I 表示 int[][Ljava/lang/Object; 表示Object[]
  • 方法签名格式:(参数签名)返回值签名,无参数写()

例如 void log(String tag, Object…… args) 的签名是:(Ljava/lang/String;[Ljava/lang/Object;)V

不复杂但容易忽略的是异常检查和引用管理——每次 JNI 调用后建议用 env->ExceptionCheck() 判断是否出错,并及时清理局部引用,否则可能引发内存泄漏或 JVM 崩溃。

站长
版权声明:本站原创文章,由 站长 2025-12-24发表,共计2183字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
1a44ec70fbfb7ca70432d56d3e5ef742
text=ZqhQzanResources