我有一个JNI代码,用于从java调用.Net API。
在一次调用中,我将一个java字节数组转换为用于.Net调用的无符号char数组。
创建的未签名的char数组被封装在一个Java对象上,在该Java对象的最终调用过程中,我将清除它
但在连续运行时,内存会不断构建,最终导致OutOfMemoryException。
以下是创建无符号char数组的代码
jbyte* messageBodyNativeJByteBuffer = env->GetByteArrayElements(jByteArrayValue,NULL);
if(messageBodyNativeJByteBuffer == NULL){
RaiseError(DNJNI_ERROR_ALLOCATE, "unsigned char array");
}
jsize arrayLength = env->GetArrayLength(jByteArrayValue);
array<unsigned char>^ dataArray = gcnew array<unsigned char>(arrayLength);
try{
for(int i=0;i<arrayLength;i++){
dataArray[i] = messageBodyNativeJByteBuffer[i];
}
return dataArray;
}finally{
// Release the UTF8 bytes
cout << "Inside BuildByteArray finally block.";
env->ReleaseByteArrayElements(jByteArrayValue, messageBodyNativeJByteBuffer,0);
cout << "Inside BuildByteArray finally block - After delete messageBodyNativeJByteBuffer.";
delete messageBodyNativeJByteBuffer;
env->DeleteLocalRef(jByteArrayValue);
cout << "Inside BuildByteArray finally block - After DeleteLocalRef jByteArrayValue.";
}
以及清除的清除呼叫
Object^ object = DotNETJNIInterface::NativeState::findState(identifier);
//This if is I added recently to try deleting it, but does not help
if(object->GetType()->ToString()->Equals("System.Byte[]")){
array<unsigned char>^ toBeDeleted = dynamic_cast<array<unsigned char>^>(object);
delete [] toBeDeleted;
cout << "Deleted Byte Array by self::::";
}
DotNETJNIInterface::NativeState::removeState(identifier);
请让我知道是否有我丢失的东西导致字节数组内存无法删除。
我可以看到几个问题:
-
GetByteArrayElements()
返回的数组由ReleaseByteArrayElements()
清理,但您也在使用delete
。这是一个主要的no,很可能会损坏堆。请删除该项,然后重试。 -
如果
gcnew
抛出异常,则不会调用GetByteArrayElements()
,并且它分配的内存会泄漏。
从您的描述中也不清楚第二部分中清理代码的目的是什么,以及OutOfMemory异常是Java还是.NET异常。
顺便说一句,JDK有一个很好的实用程序jmap
,它可以用来检查JVM堆,看看问题是否是Java字节数组太多。