讲师中心 微信公众号
AI工具推荐 视频效率加速

C++ 怎么通过 JNI(Java Native Interface)实现 Android Java 层与底层 C++ 的高性能桥接

大宇酱_5465

大宇酱_5465

发布时间:2026-10-21 09:53:34

|

334人浏览过

|

来源于php中文网

原创

Java调用C++必须通过JNI函数签名,因JVM与C++内存隔离,类型无法自动转换;签名错误会导致UnsatisfiedLinkError;需严格匹配包名、类名、方法名及JNI类型编码。

c++ 怎么通过 jni(java native interface)实现 android java 层与底层 c++ 的高性能桥接

Java 层无法直接调用 C++ 函数,必须通过 JNI 接口层中转;不写对 JNIEnv* 和线程绑定逻辑,调用会崩溃或返回乱码。

为什么 Java 调用 C++ 必须走 JNI 函数签名这道“关卡”

Java 虚拟机(ART)和 C++ 运行在完全隔离的内存空间里,java.lang.String 和 std::string 不能自动转换,int[] 和 int* 也不能直接传参。JNI 强制要求你显式声明类型映射规则——这就是函数签名(如 ([BI)I 表示输入 byte 数组和 int,返回 int)。漏写、写错签名,System.loadLibrary 不报错,但首次调用 native 方法时直接抛 UnsatisfiedLinkError。

常见错误现象:

  • Java 层调用 NativeUtils.calcDesMac64() 报 No implementation found for native Lcom/mypackage/jni/CalcMac;.Native_JniCalcDesMac64
  • C++ 函数名拼错,比如写成 Java_com_mypackage_jni_CalcMac_Native_JniCalcDesMac64 却漏了下划线或大小写
  • 没加 JNIEXPORT 和 JNICALL 宏,导致符号未导出,链接失败

实操建议:

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

Android Remote Control
Android Remote Control

远程控制 Android 设备,支持截图、自动化操作手机 App 等功能。本应用使用 uiautomator2 作为底层框架,通过 ADB 连接设备,用户无需 Root(1)查看手机屏幕;(2)自动化操作手机 App;(3)远程安装/卸载应用……

下载
  • 用 javah -jni(旧版)或 Android Studio 自动生成头文件,别手敲函数名
  • 签名必须严格匹配:包名用下划线替换点,类名和方法名之间用两个下划线,参数类型用 JNI 编码([B 是 byte[],I 是 int)
  • 函数声明必须带三个固定参数:JNIEnv* env、jobject obj(或 jclass cls 对应 static 方法)、再跟 Java 参数

如何安全地在 C++ 中访问 Java 传入的 byte[] 并避免内存越界

Java 的 byte[] 在 JNI 中不是裸指针,而是 jbyteArray 类型,必须用 env->GetByteArrayElements() 或更推荐的 env->GetByteArrayRegion() 拷贝出来——前者可能触发 pinning(锁定内存),后者只读拷贝更轻量,也避免 ART GC 移动数组时出问题。

容易踩的坑:

  • 直接强制转换 (jbyte*)array,运行时崩溃或读到脏数据
  • 用了 GetByteArrayElements() 却忘记调用 ReleaseByteArrayElements(),造成内存泄漏
  • 传入空数组或 null,没做 if (array == nullptr) 判断,直接解引用

实操建议:

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

  • 优先用 env->GetByteArrayRegion(array, 0, len, (jbyte*)buf) 把数据拷进预分配的 C++ 缓冲区
  • 如果必须原地操作(如加密 inplace),用 env->GetPrimitiveArrayCritical() + ReleasePrimitiveArrayCritical(),但要极短时间完成,否则阻塞 GC
  • 所有数组长度必须用 env->GetArrayLength(array) 获取,不要信 Java 层传来的 len 参数(可能被篡改)

Java 层加载 so 库失败的三种典型原因和验证方式

System.loadLibrary("calcmac") 看似简单,实际背后涉及 ABI 匹配、路径查找、依赖解析三重校验。任一环节失败都静默失败,只在调用 native 方法时报 UnsatisfiedLinkError。

常见错误现象:

  • App 在 arm64-v8a 设备上闪退,logcat 显示 dlopen failed: library "libcalcmac.so" not found
  • so 加载成功,但调用时报 java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "logd"
  • 模拟器上正常,真机上崩溃,因为 NDK 版本太新,targetSdkVersion 太低

实操建议:

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

  • 确认 so 文件放在 src/main/jniLibs/arm64-v8a/libcalcmac.so(不是 libs/),且 gradle 中没禁用对应 ABI:ndk { abiFilters 'arm64-v8a' }
  • 用 readelf -d libcalcmac.so | grep NEEDED 检查是否依赖了高版本 libc(如 libc++.so.21),换成 libc++_shared.so 并打包进 apk
  • 在 static{} 块里加 try-catch 包裹 loadLibrary,并打印 Log.e(TAG, "load failed", e),否则异常被吞掉

从 C++ 回调 Java 方法时 JNIEnv* 不能跨线程复用

Android 的 JNI 环境(JNIEnv*)是线程绑定的。C++ 在子线程(如 decode 线程、网络回调线程)里直接用主线程传来的 env 调用 env->CallVoidMethod(),大概率 crash 或静默失败。

根本原因:

  • JNIEnv* 实际是线程局部存储(TLS)里的一个指针,每个线程有自己的副本
  • 主线程的 env 在子线程里是无效地址,ART 可能返回 null 或任意值

实操建议:

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

  • 在 Java 层传入 jobject 时,用 env->NewGlobalRef(obj) 创建全局引用,防止 Java 对象被 GC
  • 在子线程开头调用 g_jvm->AttachCurrentThread(&env, nullptr) 获取当前线程的 JNIEnv*(g_jvm 是 JavaVM*,在 JNI_OnLoad 里保存)
  • 退出前务必调用 g_jvm->DetachCurrentThread(),否则线程退出后 JVM 不释放资源
  • 回调方法尽量用 env->CallStaticXXXMethod(),避免传 jobject 生命周期管理问题

最易被忽略的一点:JNIEnv* 不是“一次获取,到处可用”,它本质上是个临时句柄,生命周期严格绑定于当前线程上下文。任何跨线程传递或缓存 env 的做法,都是在埋雷。

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

10877

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

8002

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

6932

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

1164

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

948

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

1416

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2869

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

20151

2023.08.03

Playwright 测试失败怎么办
Playwright 测试失败怎么办

Playwright测试失败专题汇集超时、定位器匹配、浏览器提前关闭、依赖与插件配置、文件上传、SSL及Docker启动等故障文章,并介绍通过截图、报告和Trace定位错误。

0

2026.10.21

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C语言中文开发手册
C语言中文开发手册

共0课时 | 0.2万人学习

极客学院ASP.NET视频教程
极客学院ASP.NET视频教程

共90课时 | 24.3万人学习

Go语言教程手册
Go语言教程手册

共23课时 | 27万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn