这段时间负责公司一款车载检测产品的平台开发和维护工作。这款产品的工作模式是通过手机端的应用与插在车上的车机设备通信,来实现一些功能。手机端代码实现上是将公司的C代码的应用移植到手机应用上,以动态链接库的方式,通过JNI层与java层交互。
产品研发和测试已经接近尾声,但是应用在测试中还是发现存在极个别的情况下接收数据失败的问题。通过几天的查找,已经完全排除了接头端的问题,也排除了C应用端的问题,那么主要问题就可能出在JNI层了,通过在jni层中加log,发现确实是存在问题,具体问题如下:
1、java通过jni层存储到消息队列中的消息,应用层通过jni层获取不到或获取不完整,一般是掉了最后一帧。
查找一圈,发现问题的根本如下:
//之前的代码
void QUEUE_MSG::getSendMsg(MSGDLLTOEXE *msg) {
if (send_msg.msg.empty()) {
//重置返回一个无效消息
msg->msgtype = 0;
msg->action_tp = 0;
msg->ui_act = 0;
msg->db_act = 0;
msg->cal_act = 0;
msg->cmd_rlen = 0;
} else {
*msg = send_msg.msg.front(); //获取消息队列中最前面的消息
send_msg.msg.pop(); // 删除消息队列中最前面的消息
}
我的理解是:这种将队列顶部的消息取出之后再删除队列中消息的操作,一般是没有什么问题的,但是如果消息队列中的指针变量指向了一块数据区域,在pop()的动作做出之后,连带着对已取出的消息造成的影响。导致已取出的消息是空消息,后续将代码修改如下之后,问题得到解决:
//之后的代码
void QUEUE_MSG::getReceiveMsg(MSGDLLTOEXE *msg) {
if(msg->msgtype == 300) {
while(receive_msg_cmd_lock == 1)
{
Delay(1);
}
receive_msg_cmd_lock