参考文章:《在 JNI 编程中避免内存泄漏》
JNI Local Reference 的生命期是在 native method 的执行期(从 Java 程序切换到 native code 环境时开始创建,或者在 native method 执行时调用 JNI function 创建),在 native method 执行完毕切换回 Java 程序时,所有 JNI Local Reference 被删除,生命期结束(调用 JNI function 可以提前结束其生命期)。
(我们实际编码中经常会自己封装一个NewStringUTF、NewObject之类的引用方法,在同一个nativeMethod中反复多次调用,其实这样是误以为LocalReference与局部变量的生命周期一致了)
实际上,每当线程从 Java 环境切换到 native code 上下文时(J2N),JVM 会分配一块内存,创建一个 Local Reference 表,这个表用来存放本次 native method 执行中创建的所有的 Local Reference。每当在 native code 中引用到一个 Java 对象时,JVM 就会在这个表中创建一个 Local Reference。比如,下面代码中我们调用 NewStringUTF() 在 Java Heap 中创建一个 String 对象后,在 Local Reference 表中就会相应新增一个 Local Reference。
Java 代码部分 class TestLocalReference { private native void nativeMethod(int i); public static void main(String args[]) { TestLocalReference c = new TestLocalReference(); //call the jni native method c.nativeMethod(1000000); } static { //load the jni library System.loadLibrary("StaticMethodCall"); } } JNI 代码,nativeMethod(int i) 的 C 语言实现 #include<stdio.h> #include<jni.h> #include"TestLocalReference.h" JNIEXPORT void JNICALL Java_TestLocalReference_nativeMethod (JNIEnv * env, jobject obj, jint count) { jint i = 0; jstring str; for(; i<count; i++) str = (*env)->NewStringUTF(env, "0"); } 运行结果 JVMCI161: FATAL ERROR in native method: Out of memory when expanding local ref table beyond capacity at TestLocalReference.nativeMethod(Native Method) at TestLocalReference.main(TestLocalReference.java:9)