c++ jni调用java方法 c++如何通过jni与android或java交互

星降

星降

2026-03-29

997人浏览

原创

在c++ jni中调用java实例方法需先获取jobject,再用getmethodid获取方法id,最后用callobjectmethod等调用;三者任一出错将崩溃或返回垃圾值。

c++ jni调用java方法 c++如何通过jni与android或java交互

如何在 C++ JNI 中调用 Java 实例方法

必须先拿到 jobject,再通过 GetMethodID 获取方法 ID,最后用 CallObjectMethod(或对应类型的方法)调用。没对象、没方法 ID、类型不匹配,三者任一出错都会崩溃或返回垃圾值。

  • 常见错误现象:java.lang.NoSuchMethodError 多半是签名写错,比如把 Ljava/lang/String; 写成 Ljava/lang/string;(大小写敏感)
  • 签名必须严格匹配:用 javap -s 查真实签名,别手写。例如 void foo(String s, int x) 对应 (Ljava/lang/String;I)V
  • 如果 Java 方法是 privatestatic,要用 GetStaticMethodID + CallStaticXXXMethod,混用会返回 NULL
  • jobject 必须是有效的本地引用(local ref),不能是已 DeleteLocalRef 过的,也不能跨线程复用

如何安全获取 Java 类和方法 ID

类名用斜杠分隔(java/lang/String),不是点号;方法 ID 不能缓存到全局变量里直接用,除非你确保类加载器没变、且做了同步。

  • 推荐写法:FindClass 后立即 NewGlobalRef 持有类引用,再 GetMethodID;否则类可能被卸载,后续调用 crash
  • Android 上 FindClass 在非主线程调用前,必须先 AttachCurrentThread,否则返回 NULL
  • 方法 ID 是运行时解析的,只要类没重定义(如热修复场景),可缓存为静态局部变量,但首次获取仍需判空
  • 别用 GetObjectClass 反推类名——它返回的是运行时实际类,可能不是你期望的父类,容易导致 GetMethodID 找不到方法

基本类型与对象参数怎么传进 Java 方法

JNI 不自动转换 C++ 类型和 Java 对象,所有参数都得手动包装。基本类型直传,对象必须是 jobject 或其子类型(如 jstringjintArray)。

C函数速查手册(CHM版)
C函数速查手册(CHM版)

C函数速查手册(CHM版)

下载
  • jstring 要用 NewStringUTF(仅支持修改过的 UTF-8)或 NewString(UCS-2),别直接传 C 字符串指针
  • byte[]NewByteArray + SetByteArrayRegion;传 String[] 得循环新建每个 jstring,再用 NewObjectArray
  • Java 方法参数是泛型(如 List<string></string>)?JNI 层无法识别泛型,只认原始类型 java/util/List,你得确保传进去的是正确实现类(如 ArrayList)的实例
  • 数组长度超过 65535 时,某些旧版 Android ART 会拒绝创建,建议分批或改用其他序列化方式

为什么 CallVoidMethod 后程序偶尔卡住或崩溃

最常踩的坑是未检查异常。JNI 调用 Java 方法时若抛出异常,JVM 不会自动终止,但后续任何 JNI 调用(包括 ExceptionCheck 以外的)都可能失败或静默失效。

  • 每次 CallXXXMethod 后,务必用 ExceptionCheck 判断是否出异常;真出了,得立刻 ExceptionDescribe 打印日志,并 ExceptionClear,否则下一次 JNI 调用大概率失败
  • 不要在 Java 方法里 throw unchecked exception 然后指望 C++ 捕获——JNI 层没有 try/catch 机制,只能靠 ExceptionCheck
  • 回调 Java 方法时,如果 Java 层执行耗时操作(如网络请求),C++ 线程会同步阻塞,Android 上还可能触发 ANR;需要异步处理时,应在 Java 层启动新线程或用 Handler
  • 释放资源要配对:NewGlobalRef 对应 DeleteGlobalRefNewLocalRef 对应 DeleteLocalRef,漏掉会导致内存泄漏或随机 crash

JNI 的边界很薄,类型、生命周期、线程、异常,四个维度只要一个没对齐,问题就藏得深、复现难。别信“差不多”,每个 jobject 都得问自己:它哪来的?谁负责删?能不能跨线程?有没有可能为空?

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

2882

3

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

418

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1486

6

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

418

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1486

6

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

418

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1486

6

全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

2025.09.18

1045

12

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

2025.09.18

563

13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
RabbitMQ 教程手册
RabbitMQ 教程手册

共0课时 | 0人学习

Linux man-pages 项目
Linux man-pages 项目

共0课时 | 0人学习

C# 教程
C# 教程

共94课时 | 20.1万人学习