JNI native memory leak - release array elements (#10981)

Summary:
Closes https://github.com/facebook/rocksdb/issues/10980

Reproduced as per the suggestion in the ticket, and `$ jcmd <PID> VM.native_memory | grep Internal` reports that we are no longer leaking internal memory with the suggested fix.

I did the repro in `MultiGetTest.java` which I have optimized imports on. It did not seem helpful to leave the test code around as it would be onerous to build a memory leak reproducer, and regression seems a remote possibility.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/10981

Reviewed By: riversand963

Differential Revision: D41498748

Pulled By: ajkr

fbshipit-source-id: 8c6dd0d608172879c8bda479c7c9c05c12d34e70
main
Alan Paxton 2 years ago committed by Facebook GitHub Bot
parent c93ba7db5d
commit 6a8920f988
  1. 9
      java/rocksjni/rocksjni.cc
  2. 5
      java/src/test/java/org/rocksdb/MultiGetTest.java

@ -1836,6 +1836,10 @@ inline bool keys_from_bytebuffers(JNIEnv* env,
jobject jkey = env->GetObjectArrayElement(jkeys, i); jobject jkey = env->GetObjectArrayElement(jkeys, i);
if (env->ExceptionCheck()) { if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException // exception thrown: ArrayIndexOutOfBoundsException
// cleanup jkey_off and jkey_len
env->ReleaseIntArrayElements(jkey_lens, jkey_len, JNI_ABORT);
env->ReleaseIntArrayElements(jkey_offs, jkey_off, JNI_ABORT);
return false; return false;
} }
char* key = reinterpret_cast<char*>(env->GetDirectBufferAddress(jkey)); char* key = reinterpret_cast<char*>(env->GetDirectBufferAddress(jkey));
@ -1844,6 +1848,11 @@ inline bool keys_from_bytebuffers(JNIEnv* env,
env->DeleteLocalRef(jkey); env->DeleteLocalRef(jkey);
} }
// cleanup jkey_off and jkey_len
env->ReleaseIntArrayElements(jkey_lens, jkey_len, JNI_ABORT);
env->ReleaseIntArrayElements(jkey_offs, jkey_off, JNI_ABORT);
return true; return true;
} }

@ -11,12 +11,17 @@ import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import org.junit.ClassRule;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
import org.rocksdb.util.TestUtil; import org.rocksdb.util.TestUtil;
public class MultiGetTest { public class MultiGetTest {
@ClassRule
public static final RocksNativeLibraryResource ROCKS_NATIVE_LIBRARY_RESOURCE =
new RocksNativeLibraryResource();
@Rule public TemporaryFolder dbFolder = new TemporaryFolder(); @Rule public TemporaryFolder dbFolder = new TemporaryFolder();
@Test @Test

Loading…
Cancel
Save