报错:
terminate called after throwing an instance of 'std::logic_error'what(): basic_string::_M_construct null not valid
java程序调用jni接口运行服务,访问就会崩溃,idea报错如上,浏览器中则是无响应,且是跨域报错(这是服务停止无法请求导致的)。多次尝试后无果,逐一排查问题。
检查java程序和接口,没有错误,然后排查jni层代码,注掉jni调用c++层的接口,发现仍然有问题,那么问题应该是出在jni层。再逐步排查发现是jstring参数解析过程出现的问题。
解决问题:
由于需要,传入了jstring参数,参数可以为空可以有数据内容,参数在jni层解析转为string传入C代码,在C代码中判断处理。这里设计的参数为空传入形式可以是info=null;或者info=“”;为此在传入“”后出现了上述报错导致程序无法运行的情况。
jni层中使用的jstring2string函数为:
string jstring2string(JNIEnv *env, jstring jstr)//若jstr为“”时报错
{
char* rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("GB2312");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
if(alen>0)
{
rtn = (char*)malloc(alen + 1);
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements(barr,ba,0);
string stemp(rtn);
free(rtn);
return stemp;
}
不难发现其中的原因:调用的jstring2string函数,传入空值"",alen=0,未处理却直接释放了相关内存,返回的也是坏内存,就会导致内存异常报错。
需要考虑到jstr=“”的情况,修改代码有:
string jstring2string(JNIEnv *env, jstring jstr)
{
char* rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("GB2312");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
if(alen>0)
{
rtn = (char*)malloc(alen + 1);
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
else
{
env->ReleaseByteArrayElements(barr,ba,0);
return "";
}
env->ReleaseByteArrayElements(barr,ba,0);
string stemp(rtn);
free(rtn);
return stemp;
}
修改后再运行程序测试就能够正常运行没有报错了,那么这个问题就解决了。