四、(2)C++访问Java的String字符串对象

我以前是学Java的,对于C++只是明白很少的知识,所以看得越多,出现的问题也越多,我只有慢慢消化了

第四讲的第二部分:在C/C++本地代码中访问Java的String字符串对象

Java与C++中字符串的区别

  1. 在Java中,使用的字符串String 对象时Unicode(UTF-16)码,即每个字符不论是中文还是英文还是符号,一个字符总是占两个字节
  2. Java通过JNI接口可以将Java的字符串转换到C/C++的宽字符串(wchar_t*),或是传回一个UTF-8的字符串(char*)到C/C++.
  3. C/C++可以通过一个看字符串或是一个UTF-8编码的字符串来创建一个Java端的String对象

JNI中操作字符串相关函数

函数作用是取得某个jstring对象相关的Java字符串,介绍了三种类型的字符串操作函数

1、GetStringChars 与 GetStringUTFChars

  • GetStringChars 取得UTF-16编码的宽字符串(jchar*)
  • GetStringUTFChars 取得UTF-8编码的字符串(char*)

const jchar *GetStringChars(jstring str, jboolean *isCopy) {
      return functions->GetStringChars(this,str,isCopy);
}
const char* GetStringUTFChars(jstring str, jboolean *isCopy) {
      return functions->GetStringUTFChars(this,str,isCopy);
}
void ReleaseStringChars(jstring str, const jchar *chars) {
     functions->ReleaseStringChars(this,str,chars);
}
void ReleaseStringUTFChars(jstring str, const char* chars) {
     functions->ReleaseStringUTFChars(this,str,chars);
}


1 )、参数

  • 第一个参数传入一个指向Java中的String对象的jstring变量.
  • 第二个参数传入jboolean  指针,标示是否对Java的String对象进行了Copy。也就是会给该指针指向的内存传入JNI_TRUE 或JNI_FALSE 标示是否进行了拷贝、NULL表示不关心是否拷贝,就不想内存赋值

2 )、这两个函数可以两种方式进行字符串的Copy

  • 开辟新内存,Java中的String拷贝到新内存中,最后返回指向这个内存地址的指针.
  • 直接返回指向Java中String的内存指针,此时 千万不能改变这个内存的内容,这会破坏String在Java中始终是常量的原则 (我们都知道Java中String为不可变对象,一旦被创建,就不能修改它的值.需要修改则需要重新创建对象 )

3 )、释放拷贝的内存

在取得字符串后,当已经不再之用,需要通过ReleaseStringChars、ReleaseStringUTFChars来释放拷贝所用的内存或释放Java的String对象的引用.(上面代码中)

  • 参数一:指定jstring变量—>本地要释放的字符串来源
  • 参数二:释放本地字符串

 

2、GetStringCritical 与 ReleaseStringCritical

为了增加直接传回Java字符串的指针的可能性(不是拷贝)JDK1.2 之后增加GetStringCritical、ReleaseStringCritical

const jchar * GetStringCritical(jstring string, jboolean *isCopy) {
      return functions->GetStringCritical(this,string,isCopy);
}
void ReleaseStringCritical(jstring string, const jchar *cstring) {
      functions->ReleaseStringCritical(this,string,cstring);
}


  1. 这两个函数之间是一个关键区,在这个关键区中不能调用JNI的其它函数或可能造成当前线程中断、等待的任何本地代码 , 否则将造成关键区代码执行期间垃圾回收器停止运作,任何触发垃圾回收器的线程也将暂停,其它触发垃圾回收器的线程不能前进,直到当前线程结束来激活垃圾回收器
  2. 关键区中不能出现中断操作,不能在 JVM 中分配新对象,否则造成 JVM 死锁.
  3. 虽然增加了直接传回Java字符串指针的可能性,不过还是需要根据实际情况传回拷贝过的字符串,如 Java 字符串是UTF-16 ,要想转成UTF-8编码还是需要进行拷贝,所以也就没有GetStringUTFCritical 这个函数

 

3、GetStringRegion 与 GetStringUTFRegion

Java 1.2中新增函数,可以实现把Java字符串直接拷贝到C++的字符串数组中,在调用这个函数之前必须有一个C++分配出来的字符串,然后通过这个函数进行字符串的拷贝

优点:函数拷贝不需要分配内存,Java中的String内容的拷贝的开销可以忽略,所以不会造成OutOFMemoryError异常.

void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) {
     functions->GetStringRegion(this,str,start,len,buf);
}
void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) {
     functions->GetStringUTFRegion(this,str,start,len,buf);
}


将指向Java字符串的 jstring 以相应编码 截取之后 传入 C++分配出来存储字符串的空间buf

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值