开发者社区 问答 正文

jni循环调用java接口发生崩溃:报错

C本地接口

JNIEnv* jniEnv = NULL;
jclass TestProvider = NULL;
jobject mTestProvider = NULL;

void CtoJavaInit(void){

   TestProvider = (*jniEnv)->FindClass(jniEnv,"com/example/jni/C2jni");
   if(NULL == TestProvider)return 2;
   jmethodID construction_id = (*jniEnv)->GetMethodID(jniEnv, TestProvider, "<init>", "()V");
   if(0 == construction_id)return 3;
   mTestProvider = (*jniEnv)->NewObject(jniEnv, TestProvider, construction_id);
   if(NULL == mTestProvider)return 4;

   SendJ = (*jniEnv)->GetMethodID(jniEnv, TestProvider, "javaSend","([BI)I");
   if(NULL == obdSendJ)return 5;
  return 0;

}

int cSend(char *data, int datalen){
int len,intresult;
jbyteArray bytes;

if(NULL == jniEnv || NULL == mTestProvider || NULL == obdSendJ)return 0;
if(NULL == data || datalen > 128)return 0;
bytes = (*jniEnv)->NewByteArray(jniEnv, datalen);
if(NULL == bytes)return 0;
(*jniEnv)->SetByteArrayRegion(jniEnv, bytes, 0, datalen, (const jbyte *)data);
(*jniEnv)->CallIntMethod(jniEnv, mTestProvider, obdSendJ, bytes, datalen);
(*jniEnv)->DeleteLocalRef(jniEnv, bytes);
return datalen;
}

JNIEXPORT void JNICALL 

 Java_nativeMethod(JNIEnv *env, jobject obj){

   char *sendtest = "test..."; 

   jniEnv = env;

   CtoJavaInit();

   cSend(sendtest, strlen(sendtest);

}

说明:

JAVA代码循环调用nativeMethod接口,nativeMethod则通过cSend将一串数据发送到java的javaSend接口

问题是:循环发送N次后(200次左右)(*jniEnv)->CallIntMethod(jniEnv, mTestProvider, obdSendJ, bytes, datalen);出现崩溃

也做过以下测试:

nativeMethod接口中做如下修改

 char *sendtest = "test..."; 

   jniEnv = env;

   if(nativeMethod_firstcall == 1)CtoJavaInit();  //只在首次调用nativeMethod才进行接口初始化

   cSend(sendtest, strlen(sendtest);

但结果是软件更快崩溃

也试过在每次nativeMethod返回时释放mTestProvider,但依然没有效果

请大牛们指点 ...

展开
收起
kun坤 2020-06-14 10:34:54 2258 分享 版权
阿里云 AI 助理回答

从你的描述来看,问题可能出在资源管理或者JNI环境的使用上。以下是一些可能的原因和建议:

  1. 资源泄露:确保每次调用cSend后,你正确地释放了本地引用(如bytes)。虽然你已经调用了(*jniEnv)->DeleteLocalRef(jniEnv, bytes);来删除jbyteArray,但请确认没有其他地方遗漏了资源释放。

  2. 全局与局部引用混淆:检查CtoJavaInit函数中创建的对象(如mTestProvider)是否被正确管理。如果这些对象是长期使用的,需要确保它们不是局部引用,否则可能会在JNI环境的生命周期之外被错误地回收。对于长时间存活的对象,考虑使用全局引用(通过NewGlobalRef创建,使用完后记得DeleteGlobalRef)。

  3. JNI环境的有效性:你将JNIEnv* jniEnv设为全局变量,并在每次nativeMethod调用时更新它。理论上这应该工作,但要确保在多线程环境下不会同时访问jniEnv。另外,检查是否有其他线程操作导致JNI环境变得无效。

  4. 重复初始化:你提到尝试只在首次调用时执行CtoJavaInit(),这通常是一个好做法,避免不必要的重复初始化。崩溃更快可能是因为其他因素,而非这个修改本身。

  5. 异常处理:在JNI调用中添加异常捕获逻辑,比如在调用CallIntMethod前后使用ExceptionCheck检查是否有Java异常抛出,可以帮助定位问题。

  6. 内存限制或栈溢出:连续大量调用可能导致堆栈溢出或内存耗尽。检查是否有内存泄漏,以及是否有必要优化数据结构或算法减少内存使用。

  7. 线程安全:确认所有对JNI对象的操作都是线程安全的,尤其是在多线程环境下。如果nativeMethod可能被多个线程同时调用,确保对共享资源(如mTestProvider)的访问是同步的。

  8. 日志记录:增加详细的日志记录,特别是在关键的JNI调用前后,包括返回值检查,这样可以更精确地定位到失败点。

综上所述,建议重点检查资源管理、引用类型、线程安全性和异常处理方面的问题。如果以上建议不能解决问题,可能需要更详细的日志信息或使用调试工具进一步分析。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答
问答分类:
问答地址: