JNIの中でループ処理を行っていると、以下のようなエラーが発生することがあります。
ReferenceTable overflow (max=512)
Last 10 entries in JNI local reference table:
...
たとえば、Native側からJavaのRandomAccessFileにアクセスし、データを読み込む以下のようなコードがあります。
jobject rfile; // これはRandomAccessFileを指している jmethodID methodID; // これはRandomAccessFile#read(byte[], int, int)のID const int size = 1024; void *buf = malloc(size); // RandomAccessFile#readを呼び出し、Javaの配列jbufにデータを取得 jbyteArray jbuf = env->NewByteArray(size); jint ret = env->CallIntMethod(rfile, methodID, jbuf, static_cast<jint> (0), static_cast<jint> (size)); // jbufからbufにデータをコピー jboolean iscopy; void *jbytes = env->GetPrimitiveArrayCritical(jbuf, &iscopy); std::memcpy(buf, jbytes, ret); env->ReleasePrimitiveArrayCritical(jbuf, jbytes, iscopy);
これを、1回のJNI呼び出しの中で数百回呼び出すと、上記エラーが発生します。
ファイルIOの代替としてランダムアクセスしていると、すぐに発生してしまいます。
エラーの内容は、NewByteArrayで作成されたJavaのオブジェクト(jbuf)が多すぎて、参照テーブルがあふれたというものです。
1回ごとにjbufの内容はCのbufにコピーしていて、これはもういらないので、
env->DeleteLocalRef(jbuf);
を毎回呼んでやることで解決できます。