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

emoji表情引发的JNI崩溃的更多相关文章

  1. 一个emoji引发的一条血案:mysql存储emoji表情字符时报错解决

    以下是我插入一条带表情的数据到mysql后出现错误 2019-03-04 14:24:40,462 ERROR 2807 [-/139.199.27.244/-/2ms POST /api/activ ...

  2. 移动前端手机输入法自带emoji表情字符处理

    今天,测试给我提了一个BUG,说移动端输入emoji表情无法提交.很早以前就有思考过,手机输入法里自带的emoji表情,应该是某些特殊字符.既然是字符,那应该都能提交才对,可是为啥会被卡住呢?搜了一下 ...

  3. JS操作Unicode编码的emoji表情显示在页面

    前言:项目中用到了emoji表情,后端传递数据时直接是以Unicode形式,在页面总是无法展示,找尽各种方法总算是试出了一种,虽然达到效果但是并不是特别理解其中的原理并且无比笨拙,贴在这用作笔记,如果 ...

  4. IOS Emoji表情

    IOS Emoji 前言:我比较喜欢有趣的东西,有一些有趣的小东西,可能不是多么多么牛逼,也可能不需要多高深的技巧,也不会为其他什么强大的功能而服务,但是有时候将很多有趣的小东西组合起来运用,比如在你 ...

  5. 有关emoji表情以及utf-16编码

        昨日IOS组的同事遇到一个棘手的问题:当输入框内含有emoji表情时,如何获取文本框内的字符数(一个emoji表情算一个字符).       先从我最近接触的JAVA说起,JAVA中,在使用S ...

  6. iOS emoji表情转码 或者判断

    如果项目中有评论或者信息恢复的地方,往往会用到emoji,有时候如后台不支持emoji,就会显示乱码错误,我们可以把emoji转成unicode编码或者utf8编码格式传给服务器.当然如果后台服务器接 ...

  7. mysql支持IOS的Emoji表情

    原因: UTF-8编码有可能是两个.三个.四个字节.Emoji表情是4个字节,而Mysql的utf8编码最多3个字节,所以数据插不进去. 解决办法: 将Mysql的编码从utf8转换成utf8mb4 ...

  8. iOS 获取emoji表情和拦截emoji表情

      1 2 //将数字转为 #define EMOJI_CODE_TO_SYMBOL(x) ((((0x808080F0 | (x & 0x3F000) >> 4) | (x &a ...

  9. 让mysql支持emoji表情

    一.问题及原因 APP产品想对Emoji进行支持,但发现mysql数据库无法写入表情.原因是我们的mysql数据库默认用的是utf8编码,utf8编码存储时用的是三个字节,但Emoji表情是4个字节, ...

随机推荐

  1. javascript学习第三课引用类型object

    主要内容: 1.object 是所有类型的基类 实例化对象: 1. var obj = new Object(); 2. var obj = {}; 设置对象属性和方法: obj.name = 'he ...

  2. AT91-PWM应用

    步骤1: make menuconfig配置内核, 开启PWM输出功能. Device Drivers ---> Misc devices  ---> <*>Atmel AT3 ...

  3. 在指定控件位置弹出popup window

    先看效果图 黄色的就是弹出的popup window 首先自定义一个view用来显示,文件名为layout_my_view.xml <?xml version="1.0" e ...

  4. 第42讲:Scala中泛型类、泛型函数、泛型在Spark中的广泛应用

    今天来了解下scala的泛型 先让我们看下这段代码 class Triple[F,S,T](val first:F,val second: S,val third: T) val triple = n ...

  5. linux-8 基本命令---echo

    1.echo   命令用于终端显示字符或变量 格式:“echo[字符串| 变量]” @1 .echo命令的字符串输出到终端: @2 .echo查看当前SHELL的变量值(前面有$符号): @3 .查看 ...

  6. Orchard Compact v1.7.2

    1. 仅包留了Core中的Settings和Shapes, 及Modules, Themes和jQuery模块. 2. 添加了对Oracle的支持. 下载地址: 二进制: Orchard.Compac ...

  7. TypeScript 0.9.1 发布,新增 typeof 关键字

    TypeScript 0.9.1 发布了,该版本提升了编译器和语言的性能,增加新的语言特性 typeof ,更好的 this 处理等.详细介绍请看发行说明. TypeScript 是微软新推出的一种语 ...

  8. 用msbuild跑xunit单元测试

    用了Visual Studio 2015之后,发现没法跑xUnit单元测试,xUnit.net runner不支持VS2015,TestDriven.Net也不支持VS2015. 等它们支持VS201 ...

  9. 冲刺阶段day3

    day3 项目进展 今天周三,我们五个人难得的一整个下午都能聚在一起.首先我们对昨天的成果一一地查看了一遍,并且坐出了修改.后面的时间则是做出 登录界面的窗体,完善了登录界面的代码,并且实现了其与数据 ...

  10. Android---组件篇---Handler的使用(1)[转]

    在android中,有很多功能是不能放在onCreate或者onStart方法里面,因为这些功能相对 来说费时比较长,比如说下载一个文件,下载的过程比较长,但是如果写在Activity中, 那么这段时 ...