报错:
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; }
修改后再运行程序测试就能够正常运行没有报错了,那么这个问题就解决了。