JNI高阶知识总结

本文详细介绍了JNI与NDK的关系,讲解了JNIEnv与JavaVM的区别和作用,阐述了JNI加载动态库的入口函数JNI_OnLoad。此外,文章还涵盖了JNI中的字符串操作、数组操作、NIO操作、访问java对象属性、调用Java方法以及异常处理等核心知识点,旨在帮助读者全面掌握JNI的使用。
摘要由CSDN通过智能技术生成

JNI与NDK的关系

NDK可以为我们生成了C/C++的动态链接库,JNI是java和C/C++沟通的接口,两者与android没有半毛钱关系,只因为安卓是java程序语言开发,然后通过JNI又能与C/C++沟通,所以我们可以使用NDK+JNI来实现“Java+C”的开发方式。

JNIEnv与JavaVM

JNIEnv 概念 : 是一个线程相关的结构体, 该结构体代表了 Java 在本线程的运行环境 ;

JNIEnv 与 JavaVM : 注意区分这两个概念;
– JavaVM : JavaVM 是 Java虚拟机在 JNI 层的代表, JNI 全局只有一个;
– JNIEnv : JavaVM 在线程中的代表, 每个线程都有一个, JNI 中可能有很多个 JNIEnv;

JNIEnv 作用 :
– 调用 Java 函数 : JNIEnv 代表 Java 运行环境, 可以使用 JNIEnv 调用 Java 中的代码;
– 操作 Java 对象 : Java 对象传入 JNI 层就是 Jobject 对象, 需要使用 JNIEnv 来操作这个 Java 对象;

JNIEnv 体系结构
线程相关 : JNIEnv 是线程相关的, 即 在 每个线程中 都有一个 JNIEnv 指针, 每个JNIEnv 都是线程专有的, 其它线程不能使用本线程中的 JNIEnv, 线程 A 不能调用 线程 B 的 JNIEnv;

*.so的入口函数

JNI_OnLoad()与JNI_OnUnload()
当Android的VM(Virtual Machine)执行到System.loadLibrary()函数时,首先会去执行C组件里的JNI_OnLoad()函数。它的用途有二:
(1)告诉VM此C组件使用那一个JNI版本。如果你的.so档没有提供JNI_OnLoad()函数,VM会默认该.so档是使用最老的JNI 1.1版本。由于新版的JNI做了许多扩充,如果需要使用JNI的新版功能,例如JNI 1.4的java.nio.ByteBuffer,就必须藉由JNI_OnLoad()函数来告知VM。
(2)由于VM执行到System.loadLibrary()函数时,就会立即先呼叫JNI_OnLoad(),所以C组件的开发者可以藉由JNI_OnLoad()来进行C组件内的初期值之设定(Initialization) 。

这里写图片描述

这里写图片描述

这里写图片描述

JNI字符串函数

常用的JNI函数将在后续介绍,这里给出其中的字符串操作函数的函数名以及相关描述。

GetStringChars
ReleaseStringChars 获得/释放一个Unicode格式的字符串指针,可能返回一个字符串的副本

GetStringUTFChars
ReleaseStringUTFChars 获得/释放一个UTF-8格式的字符串指针,可能返回一个字符串的副本

GetStringLength 返回Unicode格式字符串的长度

GetStringUTFLength 返回UTF-8格式字符串的长度

NewString 根据Unicode格式的C字符串创建一个Java字符串

NewStringUTF 根据UTF-8格式的C字符串创建一个Java字符串

GetStringCritical
ReleaseStringCritical 获得/释放一个Unicode格式的字符串指针,可能返回一个字符串的副本【在该函数对区间内,不能使用任何JNI函数】

GetStringRegion 将Unicode格式的String复制到预分配的缓冲区中

GetStringUTFRegion 将UTF-8格式的String复制到预分配的缓冲区中

int sprintf( char *buffer, const char *format, [ argument] … );
类似于printf,根据格式化字符串format,将后续参数列表中的参数逐个输出。不过输出目标不是标准输出终端,而是字符串buffer。

字符串操作

C字符串——>java字符串

例如:下面的函数以一个C字符串为参数,并返回一个Java字符串引用类型jstring值。

jstring javastring
javastring = (*env)->NewStringUTF(env, "I LOVE YOU !");

注意,在内存溢出的情况下,NewString函数将返回NULL以通知原生代码虚拟机中有异常抛出。

java字符串转换成C字符串

为了在原生代码中使用java字符串,需要先将java字符串转换成C字符串,我们使用GetStringChars函数可以将Unicode格式的java字符串转换成C字符串,使用GetStringUTFChars函数可以将UTF-8格式的Java字符串转换成C字符串。这些函数的第三个参数均为可选参数,该可选参数名是isCopy,它让调用者确定返回的C字符串地址指向副本还是指向堆中的固定对象。例如:

const jbyte* str;
jboolean isCopy;

str = (*env)->GetStringUTFChars(env, javaString,&isCopy);
if(0 != str){
    printf("java String: %s",str);
    if(JNI_TRUE == isCopy){
        pri
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值