前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >emoji表情引发的JNI崩溃

emoji表情引发的JNI崩溃

作者头像
meteoric
发布2018-11-20 14:44:22
1.6K0
发布2018-11-20 14:44:22
举报
文章被收录于专栏:游戏杂谈游戏杂谈

今天突然接到客服那边的反馈说,有玩家反馈进游戏后不久就崩溃了,我先是怀疑网络问题,因为一连接聊天成功后就挂了。之后用logcat抓日志,发现挂在jni那里了

JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0xf0 string: '' in call to NewStringUTF from void org.cocos2dx.lib.Cocos2dxRenderer.nativeRender()

调用JNI的NewStringUTF方法就挂了,然后让后台把聊天日志全部拉出来,另存为html放到mac机上查看。发现一个特殊的表情,如下图所示:

我先让后台的同事,把所有聊天信息清理干净,这时候设备重新登录进去没有问题了。所以确定问题就是这个NewStringUTF方法引起的(但部分设备上有问题,部分设备没问题。看了一下好像是Android5.0及以后的系统就有此问题),问了其它同事,发现他们之前遇到过并且处理了。

有二种方案:一种是升级NDK,另外一种是C++传给Java时使用byte[],Java里再把byte[]转成String,避免NewStringUTF导致的崩溃。

我用的是cocos2d-x 2.x版本,找到CCImage.cpp文件,修改getBitmapFromJava方法

代码语言:javascript
复制
bool getBitmapFromJava(const char *text, int nWidth, int nHeight, CCImage::ETextAlign eAlignMask, const char * pFontName, float fontSize)
{
    JniMethodInfo methodInfo;
    if (! JniHelper::getStaticMethodInfo(methodInfo, "org/cocos2dx/lib/Cocos2dxBitmap", "createTextBitmap", 
        "([BLjava/lang/String;IIII)V"))
    {
        CCLOG("%s %d: error to get methodInfo", __FILE__, __LINE__);
        return false;
    }

    /**create bitmap
     * this method call Cococs2dx.createBitmap()(java code) to create the bitmap, the java code
     * will call Java_org_cocos2dx_lib_Cocos2dxBitmap_nativeInitBitmapDC() to init the width, height
     * and data.
     * use this appoach to decrease the jni call number
    */

    int strLen = strlen(text);
    jbyteArray byteArray = methodInfo.env->NewByteArray(strLen);
    methodInfo.env->SetByteArrayRegion(byteArray, 0, strLen, reinterpret_cast<const jbyte*>(text));


//        jstring jstrText = methodInfo.env->NewStringUTF(text);
    jstring jstrFont = methodInfo.env->NewStringUTF(pFontName);

    methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, byteArray,
        jstrFont, (int)fontSize, eAlignMask, nWidth, nHeight);

//        methodInfo.env->DeleteLocalRef(jstrText);
    methodInfo.env->DeleteLocalRef(byteArray);

    methodInfo.env->DeleteLocalRef(jstrFont);
    methodInfo.env->DeleteLocalRef(methodInfo.classID);

    return true;
}

注释部分为原来的代码,将string替换为byte[]再传给Java即可,其它地方如果也遇到JNI崩溃的问题,也按上面进行修改即可。

符一个字符串与jbyteArray的互转函数

代码语言:javascript
复制
jbyteArray as_byte_array(unsigned char* buf, int len) {
    jbyteArray array = env->NewByteArray(len);
    env->SetByteArrayRegion(array, 0, len, reinterpret_cast<jbyte*>(buf));
    return array;
}
 
unsigned char* as_unsigned_char_array(jbyteArray array) {
    int len = env->GetArrayLength(array);
    unsigned char* buf = new unsigned char[len];
    env->GetByteArrayRegion(array, 0, len, reinterpret_cast<jbyte*>(buf));
    return buf;
}

mysql 5.5之前仅支持3个字节,如果游戏中有留言等功能要存进数据库的记录,那么你就需要过滤这些字符了,不然就会插入数据报错。

更多阅读链接:

JNI UTF-8 encoding bug with some characters

Android ICS 4.0 NDK NewStringUTF is crashing down the App

A correct way to convert byte[] in java to unsigned char* in C++, and vice versa?

emoji处理方式大起底

cocos2d-x android游戏使用自己的字体

Android 上的 制表符(tab) —— 一个神奇的字符 (cocos2dx crash)

Android 上的 制表符(tab) —— 一个神奇的字符 (二)

Java Native Interface

C and C++ JNI - University of Cambridge

Java Native Interface

探索在Android中使用Emoji Font的方法

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-11-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档