jni字符串处理传递的原理
java是unicode编码,本地层则是utf-8编码
java String转化时,必须先decode转化成mirror::String,然后再转化成utf-8编码
static const char* GetStringUTFChars(JNIEnv* env, jstring java_string, jboolean* is_copy)
作⽤:将java String转化为c语⾔中的const char*
本质:
1. 将java String做decode操作 mirror::String* s = soa.Decode<mirror::String*>(java_string);
2. 取出mirror::String中的内容。const uint16_t* chars = s->GetValue();
3. unicode转码为utf-8: ConvertUtf16ToModifiedUtf8(bytes, chars, s->GetLength());
看来本地层是⽤⼀个mirror::String对象来描述⼀个decode后的字符串
char* bytes = new char[byte_count + 1];
可以看出本地层⾃⼰申请了⼀⽚内存,然后将字符串拷贝进来,返回这个字符串的const char*
很明显这个字符串占有的内存和java中对应的字符串占⽤的不是同⼀⽚内存。
natvie层只是将它拷贝到另⼀块内存区域,然后返回const char*。
void nativePrint(JNIEnv *env, jobject thiz, jstring jstr) {
const char *nativeString = (*env)->GetStringUTFChars(env, jstr, 0);
(*env)->ReleaseStringUTFChars(env, jstr, nativeString);
}
static const char* GetStringUTFChars(JNIEnv* env, jstring java_string, jboolean* is_copy) {
if (java_string == nullptr) {
return nullptr;
}
if (is_copy != nullptr) {
*is_copy = JNI_TRUE;
}
ScopedObjectAccess soa(env);
mirror::String* s = soa.Decode<mirror::String*>(java_string);
size_t byte_count = s->GetUtfLength();
char* bytes = new char[byte_count + 1];
CHECK(bytes != nullptr);  // bionic aborts anyway.
const uint16_t* chars = s->GetValue();
ConvertUtf16ToModifiedUtf8(bytes, chars, s->GetLength());
bytes[byte_count] = '\0';
return bytes;
}
-------------------------------------------------------------------------------------------------------------
static void GetStringUTFRegion(JNIEnv* env, jstring java_string, jsize start, jsize length, char* buf)
GetStringUTFRegion和GetStringUTFChars类似,只是GetStringUTFRegion()在调⽤前需要先分配⼀块⾮const内存作为参数传进来。
⽽GetStringUTFChars()则是⾃⼰申请⼀块内存。调⽤完毕后返回的const char*,说明这块内存不让别⼈修改。
最后就是GetStringUTFRegion()copy到内存是局部变量,在栈上⾯,coder不⽤管理它。
GetStringUTFChars()调⽤完后copy到的内存是new出来的,虽然navie函数栈退出后,local ref table的内存是有限的,它会帮助释放这些内存。但是当我们不需要使⽤这块内存时最好还是调⽤ReleaseStringUTFChars()去释放这块内存,以免local ref table内存不够⽤⽽溢出。
JNIEXPORT jstring JNICALL Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)
字符串常量池原理
{
char outbuf[128];
int len = (*env)->GetStringLength(env, prompt);
(*env)->GetStringUTFRegion(env, prompt, 0, len, outbuf);
printf("%s", outbuf);
}
static void GetStringUTFRegion(JNIEnv* env, jstring java_string, jsize start, jsize length, char* buf) {
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string);
ScopedObjectAccess soa(env);
mirror::String* s = soa.Decode<mirror::String*>(java_string);
if (start < 0 || length < 0 || start + length > s->GetLength()) {
ThrowSIOOBE(soa, start, length, s->GetLength());
} else {
CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
const jchar* chars = s->GetValue();
ConvertUtf16ToModifiedUtf8(buf, chars + start, length);
}
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。