• emoji表情引发的JNI崩溃


    今天突然接到客服那边的反馈说,有玩家反馈进游戏后不久就崩溃了,我先是怀疑网络问题,因为一连接聊天成功后就挂了。之后用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方法

     

    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的互转函数

    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的方法

  • 相关阅读:
    168. 吹气球
    395. 硬币排成线 II
    436. 最大正方形
    362. 滑动窗口的最大值(单调队列)
    python-网络安全编程第二天(文件操作)
    重闯Sqli-labs关卡第一天(1-4关)
    python-网络安全编程第一天(requests模块)
    PHP代码审计入门(SQL注入漏洞挖掘基础)
    PHP代码审计入门(敏感函数回溯参数过程)
    PHP核心配置基础解读
  • 原文地址:https://www.cnblogs.com/meteoric_cry/p/4960077.html
Copyright © 2020-2023  润新知