JNI--JNIenv 、JNI Types、字符串

使用介绍

JNI 是java代码与C/C++代码沟通的桥梁。使用时只需在静态代码块中依赖.so文件,调用C/C++方法使用Native修饰。

在androidStudio使用前,切记你已经在SDK Tools里下载应用了CMake、LLDB 、NDK。

  • LLDB:调试工具(后面介绍)。
  • NDK:工具集,为我们生成C/C++的动态链接库,同时参与打包整合so和java代码。
  • CMake: 编译工具将我们编写的C/C++编译成.so文件。配置文件CMakeLists.txt 。

add_Library (native-lib  SHARED  src/main/cpp/native-lib.cpp)创建并命名。参数一:表示库文件的名字;参数二:STATIC|SHARED|MODULE  STATIC是目标文件的归档文件,在链接其他目标的时候使用,SHARED开放的库;参数三:源文件地址。

target_link_libraries(native-lib2  ${log-lib}) 指定CMake应该链接到目标库的库 。参数一:指定的目标库;参数二:将目标库链接到NDK中包含的日志库。

JNIEnv 、JNI Types

JNIEnv:获取java方法和变量的环境(上下文),在jni.h中的结构指针变量的别名。

结构体

方法调用:const jint v =env->GetVersion();

jni 方法的第二个参数jobject:对象在JNI中的类型,jni类型与java类型对应表:
 

字符串

public native String setString(String s);

s_:java 传过来的字符串。

jsting类型指向JVM内部的一个字符串(Unicode字符序列),和常规的C字符串char*(UTF-8格式)不同。s_不能直接使用。

JNI提供Unicode和UTF-8之间的转换 GetStringUTFChars (jstring string , jboolean* isCopy)。

字符串使用完之后,ReleaseStringUTFChars(jstring string,const char* utf).通知JVM回收UTF-8字符串占用的内存。

其他方法:

  1. Get / ReleaseStringChars  //获取和通知释放Unicode格式编码的字符串,操作系统支持Unicode编码的字符串时,这个方法好用。
  2. Get / ReleaseStringUTFChars //获取和通知释放UTF-8格式编码的字符串
  3. GetStringLength  //获取Unicode字符串的长度。
  4. GetStringUTFLength //返回UTF-8格式字符串字节长度(不包括结尾的‘\0’)
  5. NewString  //创 建 一 个 新 的 java.lang.String 字符串对象。内容与传入的Unicode字符串相同
  6. NewStringUTF //创 建 一 个 新 的 java.lang.String 字符串对象,内容与传入的UTF-8字符串内容相同。
  7. Get / ReleaseStringCritical //获取指向Unicode格式字符串内容的指针。本机代码不能阻塞一对GET/ReleaseStringCritical调用。
  8. Get / SetStringRegion  //将Unicode格式将字符串的内容复制到或从预先分配的C缓冲区中复制。
  9. Get / SetStringUTFRegion //将UTF-8格式将字符串的内容复制到或从预先分配的C缓冲区中复制。

GetStringChars 和 GetStringUTFChars 函数中的第三个参数需要更进一步的解 释: const jchar *  GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy); 
当从 JNI 函数 GetStringChars 中返回得到字符串 B 时,如果 B 是原始字符串 java.lang.String 的拷贝,则 isCopy 被赋值为 JNI_TRUE。如果 B 和原始字符串 指向的是 JVM 中的同一份数据,则 isCopy 被赋值为 JNI_FALSE。当 isCopy 值为 JNI_FALSE 时,本地代码决不能修改字符串的内容,否则 JVM 中的原始字符串也 会被修改,这会打破 JAVA 语言中字符串不可变的规则。 通常,因为你不必关心 JVM 是否会返回原始字符串的拷贝,你只需要为 isCopy 传递 NULL 作为参数。 JVM 是否会通过拷贝原始 Unicode 字符串来生成 UTF-8 字符串是不可以预测的, 程序员最好假设它会进行拷贝,而这个操作是花费时间和内存的。一个典型的 JVM 会在 heap 上为对象分配内存。一旦一个 JAVA 字符串对象的指针被传递给本 地代码,GC 就不会再碰这个字符串。换言之,这种情况下,JVM 必须 pin 这个对 象。可是,大量地 pin 一个对象是会产生内存碎片的,因为,虚拟机会随意性地 来选择是复制还是直接传递指针。 当你不再使用一个从 GetStringChars 得到的字符串时,不管 JVM 内部是采用复 制还是直接传递指针的方式,都不要忘记调用 ReleaseStringChars。根据方法 GetStringChars 是复制还是直接返回指针,ReleaseStringChars 会释放复制对 象时所占的内存,或者 unpin 这个对象。 

JNI 不支持 Get/ReleaseStringUTFCritical,因为这样的函数在进行编码转换时很可能会促使 JVM 对数据进行复制,因为 JVM 内部表示字符串一般都是使用 Unicode 的。 

对于小字符串来说,Get/SetStringRegion 和 Get/SetString-UTFRegion 这两对 函数是最佳选择,因为缓冲区可以被编译器提前分配,而且永远不会产生内存溢 出的异常。当你需要处理一个字符串的一部分时,使用这对函数也是不错的,因 为它们提供了一个开始索引和子字符串的长度值。另外,复制少量字符串的消耗 是非常小的。

在使用 GetStringCritical 时,必须非常小心。你必须确保在持有一个由 GetStringCritical 获取到的指针时,本地代码不会在 JVM 内部分配新对象,或 者做任何其它可能导致系统死锁的阻塞性调用。 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值