I have a JNI code that is used to make calls to .Net APIs from java.
In one call, I convert a java byte array to a unsigned char array which is used for a .Net call.
The unsigned char array that is created is wrapped over a Java Object and during the finalize call of that java object, i am clearing it.
But on doing a continuous run, the memory just keeps on building which eventually ends up in OutOfMemoryException.
Here is the code that is creating the unsigned char array
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.";
}
and the clean up call, that clears it
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);
Please let me know if there is something I am missing that is causing the byte array memory not to be deleted.
I can see several problems:
The array returned by
GetByteArrayElements()is cleaned up byReleaseByteArrayElements(), but you are alsodelete-ing it. This is a major no-no and may well corrupt the heap. Remove that and try again.If
gcnewthrows an exception,GetByteArrayElements()does not get called, and the memory allocated by it leaks.It is also not clear from your description what is the purpose of the cleanup code in the second section, and whether the OutOfMemory exception is a Java or .NET exception.
As an aside, the JDK has a nice utility called
jmap, which can be used to examine the JVM heap and see if the problem is that you have too many Java byte arrays.