ZC: jstring 就是 Java中的String对象

ZC: 10.8 Unicode字符串结尾(http://www.360doc.cn/article/14233282_321497569.html)
  从GetStringChars和GetStringCritical两个方法获得的Unicode字符串不是以NULL结尾的,需要调用GetStringLength来获取字符串的长度。一些操作系统,如Windows NT中,Unicode字符串必须以两个'\0'结尾,这样的话,就不能直接把GetStringChars得到的字符串传递给Windows NT系统的API,而必须复制一份并在字符串的结尾加入两个'\0'

ZC: http://www.360doc.cn/article/14233282_321497569.html

GetStringChars和ReleaseStringChars获取以Unicode格式编码的字符串。当操作系统支持Unicode编码的字符串时,这些方法很有用。

UTF-8字符串以’\0’结尾,而Unicode字符串不是。如果jstring指向一个Unicode编码的字符串,为了得到这个字符串的长度,可以调用GetStringLength。如果一个jstring指向一个UTF-8编码的字符串,为了得到这个字符串的字节长度,可以调用标准C函数strlen。或者直接对jstring调用JNI函数GetStringUTFLength,而不用管jstring指向的字符串的编码格式。

ZC: 个人偏好的统一做法(不管是UTF8还是Unicode) : C++中分配内存 + GetStringRegion/GetStringUTFRegion复制内存  (ZC: ∵结尾非"\0\0"的问题)

字符串操作:

  A、生成一个jstring对象
    jstring (JNIEnv *)->NewString(const jchar* jstr , int size);  // ZC: 第一个参数 : UTF-8编码的字符串指针 和 Unicode(UTF-16)编码的宽字符串指针,都可以?它能自动适应?

    ZC: jstring (JNIEnv *)->NewStringUTF(const char* _pchar); // ZC: 这个函数应该 较少用到

  B、获取字符串的长度:

    jsize (JNIEnv *)->GetStringLength(jstring _jstr);

  C、将jstring对象 拷贝到 const jchar*指针字符串

    C.1、拷贝Java字符串并以UTF-8编码传入jstr
      (JNIEnv *)->GetStringRegion(jstring _jstr, jsize start, jsize len, jchar* _pjchar);

    C.2、拷贝Java字符串并以UTF-16编码传入jstr
      (JNIEnv *)->GetStringUTFRegion(jstring _jstr, jsize start, jsize len, char* _pchar);

    参数 : _jstr是一个jstring对象,start是拷贝字符串的开始位置,len是拷贝字符串的长度,jstr是目标指针字符串

    (1)、在Java1.2出来的函数,这个函数的动作是把Java字符串的内容直接拷贝到C/C++的字符串数组中,在呼叫这个函数之前必须有一个C/C++分配出来的字符串(具体看下面的例子),然后传入到这个函数中进行字符串的拷贝

    (2)、由于C/C++中分配内存开销相对小,而且Java中的String内容拷贝的开销可以忽略,更好的一点是此函数不分配内存,不会抛出OutOfMemoryError异常

    (3)、ZC: 上面出现的"这个函数"、"此函数"应该值得就是 GetStringRegion 和 GetStringUTFRegion

  D、将jstring对象转化成const jchar*字符串指针
    D.1、const jchar* (JNIEnv *)->GetStringChars(jstring _jstr, jboolean* copied);
      返回一个UTF-16编码的宽字符串(jchar*)
      参数:
        _jstr 是字符串对象
        copied是指传入的是一个jboolean指针,用来标识是否对Java的String对象进行了拷贝的,如果传入的这个jboolean指针不是NULL,则它会给该指针所指向的内存传入JNI_TRUE或JNI_FALSE标识是否进行了拷贝,传入NULL表示不关心是否拷贝字符串,它就不会给jboolean* 指向的内存赋值

      其对应的释放内存指针的方法:
      (JNIEnv *)->ReleaseStringChars(jstring _jstr, const jchar* _pjchar);
      参数:
        _jstr 是jstring对象,
        _pjchar是字符串指针

    D.2、const char* (JNIEnv *)->GetStringUTFChars(jstring _jstr , jboolean* copied)
      这个方法是可以取得UTF-8编码的字符串(char*)
      参数的含义和GetStringChars方法是一样的

      这个方法也有对应的一个释放内存的方法:
      (JNIEnv *)->ReleaseStringUTFChars(jstring _jstr , const char* _pchar);
        参数的含义和上面的ReleaseStringChars方法的参数的含义是一样的

    需要注意的是:
“(来自 http://www.360doc.cn/article/14233282_321497569.html)
  当从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这个对象。
” ZC: 这里的 JVM的pin操作,没有查到具体的解释...

  E、将jstring对象转化成const jchar*字符串指针  (ZC: 带 临界区 操作[互斥/死锁])
    const jchar* (JNIEnv *)->GetStringCritical(jstring _jstr, jboolean* copied);
    参数:
      _jstr 是字符串对象,
      copied 上面的方法已经做了解释了,这里就不多说了

    这个方法的作用是为了增加直接传回指向Java字符串的指针的可能性(而不是拷贝),JDK1.2出来了新的函数GetStringCritical/ReleaseStringCritical,在GetStringCritical/ReleaseStringCritical之间是一个关键区,在这个关键区域之间不能呼叫JNI的其他函数和会造成当前线程中断,或是会让当前线程等待的任何本地代码,否则将造成关键区代码执行期间垃圾回收器停止运作,任何触发垃圾回收器的线程也会暂停,其他的触发垃圾回收器的线程不能前进直到当前线程结束而激活垃圾回收器
    在关键区域中千万不要出现中断操作,或是在JVM中分配任何新对象,否则会造成JVM死锁
    虽说这个函数会增加直接传回指向Java字符串的指针的可能性,不过还是会根据情况传回拷贝过的字符串 (ZC: 好蛋疼...)
    不支持GetStringUTFCritical,没有这样的函数,由于Java字符串用的是UTF-16,要转成UTF-8编码的字符串始终需要进行一次拷贝,所以没有这样的函数
这个方法和第四个方法(ZC: GetStringChars)是一样的功能

    其对应的释放内存指针的方法:
      (JNIEnv *)->ReleaseStringCritical(jstring _jstr, const jchar* _pjchar);

1、

2、

3、

4、

5、

JNI_Z_09_Java的字符串的更多相关文章

  1. Python高手之路【六】python基础之字符串格式化

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...

  2. 测试一下StringBuffer和StringBuilder及字面常量拼接三种字符串的效率

    之前一篇里写过字符串常用类的三种方式<java中的字符串相关知识整理>,只不过这个只是分析并不知道他们之间会有多大的区别,或者所谓的StringBuffer能提升多少拼接效率呢?为此写个简 ...

  3. java中的字符串相关知识整理

    字符串为什么这么重要 写了多年java的开发应该对String不陌生,但是我却越发觉得它陌生.每学一门编程语言就会与字符串这个关键词打不少交道.看来它真的很重要. 字符串就是一系列的字符组合的串,如果 ...

  4. JavaScript 字符串实用常操纪要

    JavaScript 字符串用于存储和处理文本.因此在编写 JS 代码之时她总如影随形,在你处理用户的输入数据的时候,在读取或设置 DOM 对象的属性时,在操作 Cookie 时,在转换各种不同 Da ...

  5. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  6. Redis的简单动态字符串实现

    Redis 没有直接使用 C 语言传统的字符串表示(以空字符结尾的字符数组,以下简称 C 字符串), 而是自己构建了一种名为简单动态字符串(simple dynamic string,sds)的抽象类 ...

  7. ASP.NET加密和解密数据库连接字符串

    大家知道,在应用程序中进行数据库操作需要连接字符串,而如果没有连接字符串,我们就无法在应用程序中完成检索数据,创建数据等一系列的数据库操作.当有人想要获取你程序中的数据库信息,他首先看到的可能会是We ...

  8. Javascript正则对象方法与字符串正则方法总结

    正则对象 var reg = new Regexp('abc','gi') var reg = /abc/ig 正则方法 test方法(测试某个字符串是否匹配) var str = 'abc123'; ...

  9. 微信小程序中利用时间选择器和js无计算实现定时器(将字符串或秒数转换成倒计时)

    转载注明出处 改成了一个单独的js文件,并修改代码增加了通用性,点击这里查看 今天写小程序,有一个需求就是用户选择时间,然后我这边就要开始倒计时. 因为小程序的限制,所以直接选用时间选择器作为选择定时 ...

随机推荐

  1. mongoDB之find()

    一.find方法 db.collection_name.find();查询 查询所有结果 1) db.users.find();类似于select * from users; 指定返回那些列(键) 2 ...

  2. Oracle数据库的归档模式(archivelog mode)

    Oracle数据库可以运行在2种模式下: 归档模式(archivelog) 归档模式可以提高Oracle数据库的可恢复性,生产数据库都应该运行在此模式下,归档模式应该和相应的备份策略相结合,只有归档模 ...

  3. amazonservices api 抽象类 Class Abstraction

    http://php.net/manual/zh/language.oop5.abstract.php MWSOrdersPHPClientLibrary-2013-09-01._V533357711 ...

  4. JS产品分类列表练习

    CSS: ;;} ul,li{list-style: none;} body{color: #666;background: #f5f5f5;} a{text-decoration: none;col ...

  5. CNI插件实现框架---以loopback为示例

    以最简单的loopback插件作为实例,来分析CNI plugin的执行流程 // cni/plugins/loopback/loopback.go 1.func main() main函数只是简单地 ...

  6. node.js---sails项目开发(5)---用户表的建立

    1. ctrl+c  暂停sails项目  ,输入如下命令,创建一个user表 sails generate api user 2.在api目录分别建立了两个文件  api/controllers/U ...

  7. 生信笔记-mooc【武大】

    .DNA拓扑学 在拓扑结构的限制下,DNA进行复制等过程.还有连环数=扭转数+缠绕数. 2.拓扑异构酶 DNA变性破坏了两条链之间碱基形成的氢键.和拓扑异构酶是不同的. 3.RNA的组成和结构特点 R ...

  8. Hadoop十年解读与发展预测

    编者按:Hadoop于2006年1月28日诞生,至今已有10年,它改变了企业对数据的存储.处理和分析的过程,加速了大数据的发展,形成了自己的极其火爆的技术生态圈,并受到非常广泛的应用.在2016年Ha ...

  9. JS 中的substring ,substr ,slice,split,join

    substr with different arguments passed in: str.substring(startNum,stopNum ); str.slice(startNum,stop ...

  10. Python-Cpython解释器支持的进程与线程

    一.Python并发编程之多进程 1. multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在pyt ...