Android JNI ReleaseByteArrayElements不起作用

时间:2015-10-08 15:51:25

标签: android android-ndk java-native-interface

我在使用Android JNI时遇到了问题。我从本机C调用一个java方法。一切正常,但几秒后APP崩溃,因为最多512个JNI引用的内容已满(或内存已满)。

这是我的代码:

int jniBluetoothSend( TJNIAdapter *pAdapter, byte *data, int dwLength )
{
JNIEnv *pEnv;
JavaVM *pVm = NULL;
jclass cls;
jmethodID methodId;
int nRet;
jbyteArray aData;

if ( pAdapter )
{
   pVm = pAdapter->pVm;
   ( *pVm )->AttachCurrentThread( pVm, &pEnv, NULL );

   if ( pAdapter->pClasses != NULL && pAdapter->pClasses->hgs_bluetooth != NULL )
   {
      // get function
      methodId = ( *pEnv )->GetMethodID( pEnv, pAdapter->pClasses->hgs_bluetooth, "write", "([BI)I" );
      if ( methodId )
      {
         aData = ( *pEnv )->NewByteArray( pEnv, dwLength);
         ( *pEnv )->SetByteArrayRegion( pEnv, aData, 0, dwLength, data);
         // write Data to device
         nRet = ( *pEnv )->CallIntMethod( pEnv, g_hgsBthObject, methodId, aData, dwLength );

         // and delete Reference -> so GC can cleanup
         ( *pEnv )->DeleteLocalRef( pEnv, aData );
      }
   }
   //( *pVm )->DetachCurrentThread( pVm ); -> // crashes as soon as getting called
}
return nRet;

}

每次调用“ReleaseByteArrayElements()”会在dalvik的Android日志中显示警告:

JNI: unpinPrimitiveArray(0x428e84a8) failed to find entry (valid=1)

所以,我认为,问题是,创建的数组没有被释放。但我不知道,如何以正确的方式做到这一点。

任何人都可以帮我吗? 谢谢!

修改

我做了几次测试。 如果我将DetachCurrentThread函数添加到第二个if()的底部,则APP会崩溃,如果DetachCurrentThread被调用的话。

但我在其他功能中添加了DeleteLocalRef,APP不再崩溃。

所以我的问题是:我是否必须在我呼叫DetachCurrentThread的每个功能中拨打AttachCurrentThread,或者如果我将该呼叫一次发送到APP结尾就足够了吗?

还更新了代码

1 个答案:

答案 0 :(得分:2)

  

每次ReleaseByteArrayElements()被调用时,dalvik都会在Android日志中显示警告:

     

JNI:unpinPrimitiveArray(0x428e84a8)找不到条目(valid = 1)

ReleaseByteArrayElements旨在与先前对GetByteArrayElements的调用配对。来自Oracle's documentation

  

发布< PrimitiveType> ArrayElements例程
  void Release<PrimitiveType>ArrayElements(JNIEnv *env, ArrayType array, NativeType *elems, jint mode);

     

一系列函数,通知VM本机代码不再需要访问elems。 elems参数是使用相应的array函数从Get<PrimitiveType>ArrayElements()派生的指针。

由于您没有拨打GetByteArrayElements,因此您也不应该致电ReleaseByteArrayElements

请注意,SetByteArrayRegion()函数不是固定数组的函数之一,因此它不需要发布。