jni中的字符编码问题

    以前在使用jni中,发现jni字符问题,另外jni还存在着线程的不安全性,着实感觉jni不怎么地,但是目前没有好的jni的替代方案,这次介绍的是jni字符编码问题中需要注意的一个问题。

    一般我们使用的是utf8字符编码,在确认是utf8编码的同时,我们从java字串传递到c/c++库的字串是有个一个标准的接收过程,这个过程我们暂且称之为:编码传递
    编码传递是将jstring类型转换为char *或者const char*类型,其中在转换的过程中,需要有对字符编码的处理:

JNIEXPORT void JNICALL Java_com_alibaba_judystore_JudyStoreClient_modify(JNIEnv *env, jobject obj, jstring string, jboolean isOffer)
{
    const char *key = env->GetStringUTFChars(string, 0);
    jsClient->modify(key, isOffer);
    env->ReleaseStringUTFChars(string, key);
}
上面使用了jni内置的GetStringUTFChars来接收jstring,然后返回一个const char*类型,值得注意的是,这个这个指针分配的内存需要以ReleaseStringUTFChars方式释放,而不是delete和free。
    另外,有一种jni的方式是读取本地的字符串,见文件:jniutils.h,其中:
char *JNU_GetStringNativeChars(JNIEnv *env, jstring jstr)
{
    jbyteArray bytes = 0;
    char *result = 0;
    jthrowable exc;

    if (env->EnsureLocalCapacity(2) < 0)
    {
        return 0; /* out of memory error */
    }

    if (!MID_String_getBytes)
        MID_String_getBytes = env->GetMethodID(env->FindClass(
                "java/lang/String"), "getBytes", "()[B");

    bytes = (jbyteArray) env->CallObjectMethod(jstr, MID_String_getBytes);
    exc = env->ExceptionOccurred();

    if (!exc)
    {
        jint len = env->GetArrayLength(bytes);
        result = new char[len + 1];
        if (result == 0)
        {
            JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0);
            env->DeleteLocalRef(bytes);
            return 0;
        }

        env->GetByteArrayRegion(bytes, 0, len, (jbyte *) result);
        result[len] = 0; /* NULL-terminate */
    }
    else
    {
        env->DeleteLocalRef(exc);
    }

    env->DeleteLocalRef(bytes);

    return result;
}
然后使用JNU_GetStringNativeChars来调用:
JNIEXPORT jstring JNICALL Java_com_alibaba_offer_OfferClassifierJNI_nativeClassify
  (JNIEnv *env, jobject, jstring jstr)
{
    char *cstr = JNU_GetStringNativeChars(env, jstr);
    string str = string(cstr);
    double score;
    string category = classifier->classify(str, score);
    delete cstr;
    return env->NewStringUTF(category.c_str());
}
这样,会造成如果当前环境(locale)不是UTF-8,会造成编码传递失效,导致不可预料的错误。

Monthly Archives

Pages

Powered by Movable Type 7.7.2

About this Entry

This page contains a single entry by Cnangel published on June 21, 2009 12:00 PM.

Pidgin and Yahoo (1) was the previous entry in this blog.

Pidgin and Yahoo (2) is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.