Android JNI ReleaseByteArrayElements 不起作用
Android JNI ReleaseByteArrayElements does not work
我在使用 Android JNI 时遇到问题。我从本机 C 调用了一个 java 方法。一切正常,但几秒钟后应用程序崩溃,因为 JNI refs 的最大 512 个条目已满(或内存已满)。
这是我的代码:
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()" 时都会在 Android 来自 dalvik 的日志中显示警告:
JNI: unpinPrimitiveArray(0x428e84a8) failed to find entry (valid=1)
所以,我认为问题是,创建的数组没有被释放。但我不知道,如何以正确的方式做到这一点。
谁能帮我解决这个问题?
谢谢!
编辑
我做了几个测试。
如果我将 DetachCurrentThread
函数添加到第二个 if() 的底部,如果 DetachCurrentThread
被调用,APP 会崩溃。
但是我在另外一个功能里添加了DeleteLocalRef
,APP没有崩溃了。
所以我的问题是:我是否必须在调用 AttachCurrentThread
的每个函数中调用 DetachCurrentThread
或者如果我调用一次到 APP 结束就足够了吗?
也更新了代码
Everytime ReleaseByteArrayElements()
gets called a warning shows up in Android Log from dalvik:
JNI: unpinPrimitiveArray(0x428e84a8) failed to find entry (valid=1)
ReleaseByteArrayElements
旨在与之前对 GetByteArrayElements
的调用配对。来自 Oracle's documentation:
Release<PrimitiveType>ArrayElements Routines
void Release<PrimitiveType>ArrayElements(JNIEnv *env,
ArrayType array, NativeType *elems, jint mode);
A family of functions that informs the VM that the native code no longer needs access to elems. The elems
argument is a pointer derived from array
using the corresponding Get<PrimitiveType>ArrayElements()
function.
因为你没有调用 GetByteArrayElements
你也不应该调用 ReleaseByteArrayElements
.
请注意,SetByteArrayRegion()
函数不是固定数组的函数之一,因此不需要发布。
我在使用 Android JNI 时遇到问题。我从本机 C 调用了一个 java 方法。一切正常,但几秒钟后应用程序崩溃,因为 JNI refs 的最大 512 个条目已满(或内存已满)。
这是我的代码:
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()" 时都会在 Android 来自 dalvik 的日志中显示警告:
JNI: unpinPrimitiveArray(0x428e84a8) failed to find entry (valid=1)
所以,我认为问题是,创建的数组没有被释放。但我不知道,如何以正确的方式做到这一点。
谁能帮我解决这个问题? 谢谢!
编辑
我做了几个测试。
如果我将 DetachCurrentThread
函数添加到第二个 if() 的底部,如果 DetachCurrentThread
被调用,APP 会崩溃。
但是我在另外一个功能里添加了DeleteLocalRef
,APP没有崩溃了。
所以我的问题是:我是否必须在调用 AttachCurrentThread
的每个函数中调用 DetachCurrentThread
或者如果我调用一次到 APP 结束就足够了吗?
也更新了代码
Everytime
ReleaseByteArrayElements()
gets called a warning shows up in Android Log from dalvik:JNI: unpinPrimitiveArray(0x428e84a8) failed to find entry (valid=1)
ReleaseByteArrayElements
旨在与之前对 GetByteArrayElements
的调用配对。来自 Oracle's documentation:
Release<PrimitiveType>ArrayElements Routines
void Release<PrimitiveType>ArrayElements(JNIEnv *env, ArrayType array, NativeType *elems, jint mode);
A family of functions that informs the VM that the native code no longer needs access to elems. The
elems
argument is a pointer derived fromarray
using the correspondingGet<PrimitiveType>ArrayElements()
function.
因为你没有调用 GetByteArrayElements
你也不应该调用 ReleaseByteArrayElements
.
请注意,SetByteArrayRegion()
函数不是固定数组的函数之一,因此不需要发布。