Skip to content

Commit

Permalink
修复Android平台下不可识别字符转换成java字符串时发生JNI异常问题
Browse files Browse the repository at this point in the history
  • Loading branch information
vimfung committed May 19, 2019
1 parent 4c2759b commit 8932a85
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ jobject LuaJavaConverter::convertToJavaObjectByLuaValue(JNIEnv *env, LuaContext
}
case LuaValueTypeString:
{
retObj = env->NewStringUTF(luaValue->toString().c_str());
retObj = LuaJavaEnv::newString(env, luaValue -> toString());
break;
}
case LuaValueTypeData:
Expand Down Expand Up @@ -811,7 +811,8 @@ jobject LuaJavaConverter::convertToJavaObjectByLuaValue(JNIEnv *env, LuaContext
std::string key = i -> first;
LuaValue *item = i -> second;

jstring keyStr = env -> NewStringUTF(key.c_str());
jstring keyStr = LuaJavaEnv::newString(env, key);

jobject itemObj = LuaJavaConverter::convertToJavaObjectByLuaValue(env, context, item);
if (keyStr != NULL && itemObj != NULL)
{
Expand Down
83 changes: 79 additions & 4 deletions Source/Android/luascriptcore/src/main/jni/LuaJavaEnv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ static LuaValue* _luaMethodHandler (LuaContext *context, std::string methodName,
static jmethodID invokeMethodID = env -> GetMethodID(contenxtClass, "methodInvoke", "(Ljava/lang/String;[Lcn/vimfung/luascriptcore/LuaValue;)Lcn/vimfung/luascriptcore/LuaValue;");
static jclass luaValueClass = LuaJavaType::luaValueClass(env);

jstring jMethodName = env -> NewStringUTF(methodName.c_str());
jstring jMethodName = LuaJavaEnv::newString(env, methodName);

//参数
jobjectArray argumentArr = env -> NewObjectArray(arguments.size(), luaValueClass, NULL);
Expand Down Expand Up @@ -134,7 +134,7 @@ static LuaValue* _luaThreadHandler (LuaContext *context, const std::string & met
static jmethodID invokeMethodID = env -> GetMethodID(contenxtClass, "methodInvoke", "(Ljava/lang/String;[Lcn/vimfung/luascriptcore/LuaValue;)Lcn/vimfung/luascriptcore/LuaValue;");
static jclass luaValueClass = LuaJavaType::luaValueClass(env);

jstring jMethodName = env -> NewStringUTF(methodName.c_str());
jstring jMethodName = LuaJavaEnv::newString(env, methodName);

//参数
jobjectArray argumentArr = env -> NewObjectArray(arguments.size(), luaValueClass, NULL);
Expand Down Expand Up @@ -188,7 +188,7 @@ static void _luaExceptionHandler (LuaContext *context, std::string const& messag
{
jclass exceptHandlerCls = env -> GetObjectClass(exceptHandler);

jstring messageStr = env -> NewStringUTF(message.c_str());
jstring messageStr = LuaJavaEnv::newString(env, message);
jmethodID onExceptMethodId = env -> GetMethodID(exceptHandlerCls, "onException", "(Ljava/lang/String;)V");
env -> CallVoidMethod(exceptHandler, onExceptMethodId, messageStr);
env -> DeleteLocalRef(messageStr);
Expand All @@ -214,7 +214,7 @@ static void _luaExportsNativeTypeHandler(LuaContext *context, std::string const&
static jclass contenxtClass = LuaJavaType::contextClass(env);
static jmethodID invokeMethodID = env -> GetMethodID(contenxtClass, "exportsNativeType", "(Ljava/lang/String;)V");

jstring jTypeName = env -> NewStringUTF(typeName.c_str());
jstring jTypeName = LuaJavaEnv::newString(env, typeName);

env -> CallVoidMethod(jcontext, invokeMethodID, jTypeName);

Expand Down Expand Up @@ -507,4 +507,79 @@ jobject LuaJavaEnv::getExportTypeManager(JNIEnv *env)
jclass LuaJavaEnv::findClass(JNIEnv *env, std::string className)
{
return env -> FindClass(className.c_str());
}

jstring LuaJavaEnv::newString(JNIEnv *env, std::string str)
{
const char *cstr = str.c_str();
LuaJavaEnv::fixedUTFString((char *)cstr);
return env -> NewStringUTF(cstr);
}


void LuaJavaEnv::fixedUTFString(char* bytes)
{
char three = 0;
while (*bytes != '\0')
{
unsigned char utf8 = (unsigned char)*(bytes++);
three = 0;
// Switch on the high four bits.
switch (utf8 >> 4)
{
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
// Bit pattern 0xxx. No need for any extra bytes.
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0f:
/*
* Bit pattern 10xx or 1111, which are illegal start bytes.
* Note: 1111 is valid for normal UTF-8, but not the
* modified UTF-8 used here.
*/
LOGI("-------------- Bit pattern 10xx or 1111");
*(bytes-1) = '?';
break;
case 0x0e:
// Bit pattern 1110, so there are two additional bytes.
LOGI("-------------- Bit pattern 1110");
utf8 = (unsigned char)*(bytes++);
if ((utf8 & 0xc0) != 0x80)
{
--bytes;
*(bytes-1) = '?';
break;
}
three = 1;
// Fall through to take care of the final byte.
case 0x0c:
case 0x0d:
// Bit pattern 110x, so there is one additional byte.
LOGI("-------------- Bit pattern 110x");
utf8 = (unsigned char)*(bytes++);
if ((utf8 & 0xc0) != 0x80)
{
--bytes;
if (three)
{
--bytes;
}

*(bytes-1)='?';
}
break;
default:
break;
}
}
}
21 changes: 21 additions & 0 deletions Source/Android/luascriptcore/src/main/jni/LuaJavaEnv.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,33 @@ class LuaJavaEnv : public LuaObject
*/
static jclass findClass(JNIEnv *env, std::string className);

/**
* 创建Java字符串,使用该方法可以避免因为字符编码问题导致的异常。
*
* @param env JNI环境
* @param str 字符串
* @return Java字符串
*/
static jstring newString(JNIEnv *env, std::string str);

private:

JNIEnv *_jniEnv;
bool _attachedThread;
int _count;

/**
* 修复UTF字符串转换报错。
* 由于某些字符编码对于JVM来说并不支持,调用JNI的NewStringUTF会抛出下面异常
* "NI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte xxxx"
* 可以使用该方法先进行修复转换,然后再创建字符串。
*
* 注:对于特殊字符串转换后将会已?号代替
*
* @param bytes 字符串
*/
static void fixedUTFString(char* bytes);

};


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ LuaValue* LuaJavaExportMethodDescriptor::invokeClassMethod(LuaSession *session,
jobject jContext = LuaJavaEnv::getJavaLuaContext(env, context);

std::string methodNameString = StringUtils::format("%s_%s", name().c_str(), methodSignature().c_str());
jstring methodName = env -> NewStringUTF(methodNameString.c_str());

jstring methodName = LuaJavaEnv::newString(env, methodNameString);

int index = 0;
jobjectArray jArgs = env -> NewObjectArray((jsize)arguments.size(), LuaJavaType::luaValueClass(env), NULL);
Expand Down Expand Up @@ -84,7 +85,7 @@ LuaValue* LuaJavaExportMethodDescriptor::invokeInstanceMethod(LuaSession *sessio
jobject jContext = LuaJavaEnv::getJavaLuaContext(env, context);

std::string methodNameString = StringUtils::format("%s_%s", name().c_str(), methodSignature().c_str());
jstring methodName = env -> NewStringUTF(methodNameString.c_str());
jstring methodName = LuaJavaEnv::newString(env, methodNameString);

LuaArgumentList::iterator it = arguments.begin();
LuaJavaObjectDescriptor *objectDescriptor = (LuaJavaObjectDescriptor *)((*it) -> toObject());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ LuaValue* LuaJavaExportPropertyDescriptor::invokeGetter(LuaSession *session, Lua
jmethodID invokeMethodId = env -> GetMethodID(LuaJavaType::exportTypeManagerClass(env), "getterMethodRoute", "(Lcn/vimfung/luascriptcore/LuaContext;Ljava/lang/Object;Ljava/lang/String;)Lcn/vimfung/luascriptcore/LuaValue;");

jobject jContext = LuaJavaEnv::getJavaLuaContext(env, context);

jstring methodName = env -> NewStringUTF(name().c_str());
jstring methodName = LuaJavaEnv::newString(env, name());

LuaJavaObjectDescriptor *objectDescriptor = (LuaJavaObjectDescriptor *)instance;
jobject jReturnValue = env -> CallObjectMethod(jExportTypeManager, invokeMethodId, jContext, objectDescriptor -> getJavaObject(), methodName);
Expand Down Expand Up @@ -66,7 +65,7 @@ void LuaJavaExportPropertyDescriptor::invokeSetter(LuaSession *session, LuaObjec
jmethodID invokeMethodId = env -> GetMethodID(LuaJavaType::exportTypeManagerClass(env), "setterMethodRoute", "(Lcn/vimfung/luascriptcore/LuaContext;Ljava/lang/Object;Ljava/lang/String;Lcn/vimfung/luascriptcore/LuaValue;)V");

jobject jContext = LuaJavaEnv::getJavaLuaContext(env, context);
jstring methodName = env -> NewStringUTF(name().c_str());
jstring methodName = LuaJavaEnv::newString(env, name());

LuaJavaObjectDescriptor *objectDescriptor = (LuaJavaObjectDescriptor *)instance;

Expand Down

0 comments on commit 8932a85

Please sign in to comment.