Android C++系列:认识JNI

简介: JNI不仅仅是Android特有的,它是属于Java平台的,它允许在Java虚拟机内运行的java代码与其他编程语言(如c, c++和汇编语言)编写的程序和库进行交互。Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是并不是说不能使用其他编程语言,只要调用约定受支持就可以了。不同语言编写的程序之间调用也不是Java和C++特有的,Java可以调用C++,python、go语言都可以。

image.png


1. 什么是JNI


JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植。


JNI不仅仅是Android特有的,它是属于Java平台的,它允许在Java虚拟机内运行的java代码与其他编程语言(如c, c++和汇编语言)编写的程序和库进行交互。Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是并不是说不能使用其他编程语言,只要调用约定受支持就可以了。不同语言编写的程序之间调用也不是Java和C++特有的,Java可以调用C++,python、go语言都可以。


JNI使得在 Java 虚拟机内运行的 Java 代码能够与其它编程语言互相操作,包括创建本地方法、更新Java对象、调用Java方法,引用 Java类,捕捉和抛出异常等,也允许 Java代码调用 C/C++或汇编语言编写的程序和库。作为一个标准程序接口,它没有对底层 Java虚拟机的实现施加任何限制,并具有以下特点:


  • 二进制兼容。本地方法库与同一平台上所有Java 虚拟机之间实现二进制兼容,即对于给定平台开发人员只需要维护一种版本的本地方法库。但是同时也丧失了跨平台性,想想我们Android只编译arm平台的so库,就会导致无法在x86平台运行。


  • 效率高。为了实现实时系统,JNI 在效率与虚拟机无关性之间进行了优化,以保障高效运行。


  • 功能强。JNI 提供了大量的函数及接口让本地方法与Java 虚拟机内核相互操作,增强两者的功能。


2. 为什么会有JNI


JNI产生的原因和背景是什么呢?我们熟练掌握一门语言后为什么还要再用另一门语言去写呢?它是出于以下几方面的考虑:


  1. 历史程序复用:很多已经使用其他语言实现的功能,我们可以直接拿来主义,编译完直接使用,比如音视频领域强大的ffmpeg就是用纯c语言实现的,如果再用java实现一遍就是完全重复造轮子;
  2. 跨平台代码复用:我们想写一份代码Android、iOS、Mac、Linux公用,他们不同平台使用不同语言,怎么办呢?使用C/C++实现核心功能,然后不同平台使用不同语言的本地接口进行调用;
  3. 弥补Java平台无关性的不足:Java平台无关性导致访问系统底层或者驱动方面存在缺陷,因为我们知道操作系统都是C/C++实现,如果要访问底层硬件能力,必须要能调用C/C++接口。在Android中,我们的摄像头、麦克风、显示屏、硬件编解码器等能力在底层都是由C/C++封装;
  4. 性能考虑:有些CPU密集型操作可以使用JNI调用C/C++或者汇编实现,来提高效率。


3. JNI接口介绍


JNI对外暴露的接口主要是我们jni.h头文件,头文件里面为我们封装了JNIEnv环境变量结构和JavaVM结构体。任何方法的调用都离不开JNIEnv变量,C和C++接口还有一些差异: 在C的定义中,env是一个两级指针,而在C++的定义中,env是个一级指针。C形式需要对env指针进行双重deferencing,而且须将env作为第一个参数传给jni函数,举个简单的例子:


  • 对于demo.c:JNI 函数调用由(*env)->作前缀,目的是为了取出函数指针所引用的值,如:return (*env)->NewStringUTF(env,"HelloJNI!");  


  • 对于demo.cpp:JNIEnv 类拥有处理函数指针查找的内联成员函数,如:return env->NewStringUTF("HelloJNI!");


但是其实本质没有什么区别,一个是JNI调C,一个是JNI调C,C再调C++。


4. 经常与我们打交道的JNI


下面介绍下我们日常接触的一些使用了JNI能力的开源库:


  1. ijkplayer:做移动端播放器的对ijkplayer不会陌生,它是哔哩哔哩推出的跨平台开源播放器,由于它底层是ffmpeg实现,用到了C代码,所以需要通过JNI做包装;
  2. webrtc:谷歌开源的跨平台实时通信库,包括3A,弱网对抗等核心能力使用C/C++实现,平台层做少量包装适配;
  3. mars:微信开源的一个跨平台长连接信令库,里面还有一个高性能日志库,核心代码用C/C++实现,然后在上层不同平台做少量适配;
  4. tenforflow lite:机器学习库,C语言实现,可以一份代码编译成不同平台库。


5. 总结


本介绍了JNI概念作用以及JNI产生的北京、JNI提供的接口,以及我们常用到的一些使用了JNI的开源程序。

目录
相关文章
|
6月前
|
Android开发
Android JNI与CAN通信遇到的问题总结
Android JNI与CAN通信遇到的问题总结
227 1
|
6月前
|
Android开发
Android JNI 报错(signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr )
Android JNI 报错(signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr )
904 1
|
3月前
|
Java Android开发 C++
Android Studio JNI 使用模板:c/cpp源文件的集成编译,快速上手
本文提供了一个Android Studio中JNI使用的模板,包括创建C/C++源文件、编辑CMakeLists.txt、编写JNI接口代码、配置build.gradle以及编译生成.so库的详细步骤,以帮助开发者快速上手Android平台的JNI开发和编译过程。
242 1
|
5月前
|
Java API C++
Java JNI开发时常用数据类型与C++中数据类型转换
Java JNI开发时常用数据类型与C++中数据类型转换
211 0
|
2月前
|
Java Android开发 C++
🚀Android NDK开发实战!Java与C++混合编程,打造极致性能体验!📊
在Android应用开发中,追求卓越性能是不变的主题。本文介绍如何利用Android NDK(Native Development Kit)结合Java与C++进行混合编程,提升应用性能。从环境搭建到JNI接口设计,再到实战示例,全面展示NDK的优势与应用技巧,助你打造高性能应用。通过具体案例,如计算斐波那契数列,详细讲解Java与C++的协作流程,帮助开发者掌握NDK开发精髓,实现高效计算与硬件交互。
133 1
|
4月前
|
Java Android开发 C++
🚀Android NDK开发实战!Java与C++混合编程,打造极致性能体验!📊
【7月更文挑战第28天】在 Android 开发中, NDK 让 Java 与 C++ 混合编程成为可能, 从而提升应用性能。**为何选 NDK?** C++ 在执行效率与内存管理上优于 Java, 特别适合高性能需求场景。**环境搭建** 需 Android Studio 和 NDK, 工具如 CMake。**JNI** 构建 Java-C++ 交互, 通过声明 `native` 方法并在 C++ 中实现。**实战** 示例: 使用 C++ 计算斐波那契数列以提高效率。**总结** 混合编程增强性能, 但增加复杂性, 使用前需谨慎评估。
140 4
|
3月前
|
JSON Android开发 C++
Android c++ core guideline checker 应用
Android c++ core guideline checker 应用
|
3月前
|
JSON Android开发 数据格式
Android c++ core guideline checker 应用问题之JSON compilation database的定义如何解决
Android c++ core guideline checker 应用问题之JSON compilation database的定义如何解决
|
3月前
|
IDE 开发工具 Android开发
Android c++ core guideline checker 应用问题之clang-tidy 检查后发现的问题如何解决
Android c++ core guideline checker 应用问题之clang-tidy 检查后发现的问题如何解决
|
3月前
|
算法 Java Linux
Intellij Java JNI 调用 C++
Intellij Java JNI 调用 C++
39 0