热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JNI基础简介

导读在前面的几篇文章中,笔者介绍了C中的指针、引用、智能指针、多线程、类型转换、异常处理等相关知识点,如果想要熟练掌握,并能在实际项目中
导读

在前面的几篇文章中,笔者介绍了C++中的指针、引用、智能指针、多线程、类型转换、异常处理等相关知识点,如果想要熟练掌握,并能在实际项目中运用,光是看肯定是毫无用处,纸上谈兵永远比不上脚踏实地的实在。。。

以下是前几篇文章的回顾:
C++之RVO返回值优化
C++之const关键字
C++之指针扫盲
C++之智能指针
C++之指针与引用
C++之右值引用
C++之类型转换
C++之多线程一
C++之多线程二
C++之异常处理

从今天开始文章的内容将是一系列JNI入门的相关文章。

JNI

JNI是Java Native Interface的缩写,俗称Java本地接口,是Java语言提供的用于Java和C/C++相互沟通的机制,Java可以通过JNI调用本地的C/C++代码,本地的C/C++的代码也可以通过JNI调用Java代码。

那什么场景下可能会用到JNI呢?
1、需要提升性能时,比如说做一些底层的开发,例如音视频处理之类的,通常都会用到JNI。
2、增加破解难度,例如需要提升代码的保护级别,需要将一些敏感信息放到底层隐藏起来。
3、需要使用到一些较为成熟的底层C/C++库时。

NDK

要在安卓上使用JNI就需要用到NDK,而NDK一系列工具的集合,它提供了一系列的工具帮助开发者快使得C/C++代码能够交叉编译生成可在安卓系统上运行的动态库库或者静态库。例如我们想要将基于C的音视频处理库FFmpeg移植到安卓平台上使用的话就需要用到NDK进行交叉编译。

动态库和静态库

1、静态库

静态库是指在链接阶段,编译器将汇编生成的.o目标文件与库文件一起链接打包到可执行文件中,或者说一起链接生成最后的可执行文件。因此对应的链接方式称为静态链接。

因为静态库是在编译期间连接库文件的,所以静态库存在着可执行文件体积较大,更新维护不方便等问题。

2、动态库

动态库又叫共享库,或动态链接库。动态库在程序编译时并不会被链接到目标代码中,而是在程序运行时才被载入,不同的应用程序如果要调用同一个库,在内存中只需要有一份该共享库即可,这样就规避了空间浪费的问题。而且动态库是在程序运行时才被载入,所以相对静态库来说动态库还具有更新、部署方便等优点。
正因为动态库的这些优点,所以目前的大多数的SDK普遍才有动态库的方式。

一个简单的JNI函数

我们使用Android Studio新建一个Native C++工程,系统将自动为我们创建一个最简单的JNI函数,当然不同的包名,生成的JNI函数名不一样,例如:

extern "C" JNIEXPORT jstring JNICALL
Java_com_fly_jnitest_MainActivity_stringFromJNI(JNIEnv* env,jobject obj) {std::string hello = "Hello from C++";return env->NewStringUTF(hello.c_str());
}

1、extern “C”
在JNI函数中首先出现的是extern “C”,它是什么意思呢?这个其实写过C/C++代码的人估计都知道,就是为了在C++兼容C代码的,避免编绎器按照C++的方式去编绎C函数。
这是因为在C++中是支持函数重载的,所以在C++中函数的识别方式是通过:函数名,函数的返回类型,函数参数列表三者组合来完成的;而在C中是不支持函数重载的,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。因此需要通过extern "C"来使C++能够调用C写作的库文件。

2、jstring
这个没什么好说的,这个就是函数的返回值。

3、JNIEXPORT
JNIEXPORT是一个宏,它们在不同的平台有着不同的定义,它的主要作用是保证在本库中声明的方法,能够在其他项目中可以被调用。
例如attribute___((visibility ("default"))) 表示外部可见,类似于public修饰符 (即:可以被外部调用),而attribute___((visibility ("hidden")))表示隐藏,类似于private修饰符 (即:只能被内部调用)。

4、JNICALL
JNICALL也是一个宏,同样在不同的平台也有着不同的定义,用来表示函数的调用规范(如:__stdcall),目前在linux平台还是是空定义。

4、函数名
在上面的例子中函数名是Java_com_fly_jnitest_MainActivity_stringFromJNI,这是一个静态注册的函数名,它是与对于的Java方法有着对应关系的,他们的对应关系是:

Java_<包名>_<类名>_<方法名>

5、JNIEnv
JNIEnv* 是指向JVM函数表的指针&#xff0c;JNIEnv代表了Java环境&#xff0c;通过JNIEnv*就可以对Java端的代码进行操作&#xff0c;例如创建Java对象、访问Java对象方法、获取Java对象的属性等。
总之它是Java方法与C/C&#43;&#43;方法沟通的桥梁。

需要注意的是&#xff1a;一个JNIEnv指针仅在其相关联的线程中有效。不能将这个指针从一个线程中传递给另一个线程&#xff0c;或者在多线程中缓存和使用它。Java虚拟机在同一个线程传递给本地方法相同的JNIEnv指针&#xff0c;但是从不同线程中调用本地方法时传递的是不同的JNIEnv指针。

6、jobject
jobject 代表了定义native函数的Java类的对象实例&#xff0c;如果对于的方法是一个静态方法&#xff0c;则是jclass。

数据类型映射关系

在JNI中每种Java的基本数据类型都与C/C&#43;&#43;的基本数据类型形成映射关系。

下图展示的是Java中的基本数据类型与JNI中的基本数据类型的映射关系&#xff1a;

JNI基本数据映射

JNI以一种不透明的引用方式向原生代码传递对象&#xff0c;不透明的引用指的是指向Java虚拟机中内部数据对象的C语言指针。原生代码必须通过JNIEnv中定义的函数处理这些内部数据对象。例如对应java.lang.String的JNI对象是jstring.jstring引用的真实的值是与原生代码无关的。原生代码通过GetStringUTFChars来访问一个Java字符串的内容。

所有的JNI引用都是jobject类型。为了提高类型安全性以及保证使用的便利性&#xff0c;JNI定义了一系列引用类型&#xff0c;这些引用类型在概念上都是Jobject的子类型。这些子类型与Java语言中最常用的类型相关联。例如&#xff0c;jstring对应String, jobjectArray对应一个对象数组&#xff0c;下图是JNI引用类型以及与其所有子类型之间继承关系的列表&#xff1a;
JNI引用类型关系表

本篇作为一个开篇题&#xff0c;主要简单介绍了JNI中的一些基本的基础知识&#xff0c;关于JNI的更多用法我们将在后面的章节进行介绍。

关注我&#xff0c;一起进步&#xff0c;人生不止coding&#xff01;&#xff01;&#xff01;
微信扫码关注


推荐阅读
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • VueCLI多页分目录打包的步骤记录
    本文介绍了使用VueCLI进行多页分目录打包的步骤,包括页面目录结构、安装依赖、获取Vue CLI需要的多页对象等内容。同时还提供了自定义不同模块页面标题的方法。 ... [详细]
  • 如何用JNI技术调用Java接口以及提高Java性能的详解
    本文介绍了如何使用JNI技术调用Java接口,并详细解析了如何通过JNI技术提高Java的性能。同时还讨论了JNI调用Java的private方法、Java开发中使用JNI技术的情况以及使用Java的JNI技术调用C++时的运行效率问题。文章还介绍了JNIEnv类型的使用方法,包括创建Java对象、调用Java对象的方法、获取Java对象的属性等操作。 ... [详细]
  • PHP反射API的功能和用途详解
    本文详细介绍了PHP反射API的功能和用途,包括动态获取信息和调用对象方法的功能,以及自动加载插件、生成文档、扩充PHP语言等用途。通过反射API,可以获取类的元数据,创建类的实例,调用方法,传递参数,动态调用类的静态方法等。PHP反射API是一种内建的OOP技术扩展,通过使用Reflection、ReflectionClass和ReflectionMethod等类,可以帮助我们分析其他类、接口、方法、属性和扩展。 ... [详细]
  • Python已成为全球最受欢迎的编程语言之一,然而Python程序的安全运行存在一定的风险。本文介绍了Python程序安全运行需要满足的三个条件,即系统路径上的每个条目都处于安全的位置、"主脚本"所在的目录始终位于系统路径中、若python命令使用-c和-m选项,调用程序的目录也必须是安全的。同时,文章还提出了一些预防措施,如避免将下载文件夹作为当前工作目录、使用pip所在路径而不是直接使用python命令等。对于初学Python的读者来说,这些内容将有所帮助。 ... [详细]
  • 本文介绍了在Go语言中可见性与scope的规则,包括在函数内外声明的可见性、命名规范和命名风格,以及变量声明和短变量声明的语法。同时,还介绍了变量的生命周期,包括包级别变量和局部变量的生命周期,以及变量在堆和栈上分配的规则和逃逸分析的概念。 ... [详细]
  • 本文介绍了在Android Studio中使用命令行build gradle的方法,并解决了一些常见问题,包括手动配置gradle环境变量和解决External Native Build Issues的方法。同时提供了相关参考文章链接。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
author-avatar
eea1051113
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有