JNI使用過程中出現的ReferenceTable overflow問題
阿新 • • 發佈:2019-01-26
工作中,在使用JNI的過程中,出現程式執行崩潰的問題,通過LOG看是出現了ReferenceTable overflow問題,抓取的部分LOG如下:
W/dalvikvm( 6450): ReferenceTable overflow (max=1024)
06-07 16:33:04.377 W/dalvikvm( 6450): JNI pinned array reference table (0x56f69d08) dump:
06-07 16:33:04.377 W/dalvikvm( 6450): Last 10 entries (of 1024):
06-07 16:33:04.377 W/dalvikvm( 6450 ): 1023: 0x41e2c850 byte[] (320 elements)
06-07 16:33:04.377 W/dalvikvm( 6450): 1022: 0x41de2898 short[] (160 elements)
06-07 16:33:04.377 W/dalvikvm( 6450): 1021: 0x41c2d0a0 short[] (160 elements)
06-07 16:33:04.377 W/dalvikvm( 6450): 1020: 0x41dbe7d0 short[] (160 elements)
06-07 16:33:04.377 W/dalvikvm( 6450): 1019 : 0x41dbe678 short[] (160 elements)
06-07 16:33:04.377 W/dalvikvm( 6450): 1018: 0x41c1db18 short[] (160 elements)
06-07 16:33:04.377 W/dalvikvm( 6450): 1017: 0x41d888c0 short[] (160 elements)
06-07 16:33:04.377 W/dalvikvm( 6450): 1016: 0x41d46758 short[] (160 elements)
06-07 16:33:04.377 W/dalvikvm( 6450): 1015: 0x41d46600 short[] (160 elements)
06-07 16:33:04.377 W/dalvikvm( 6450): 1014: 0x41bdb680 char[] (17 elements)
06-07 16:33:04.377 W/dalvikvm( 6450): Summary:
06-07 16:33:04.377 W/dalvikvm( 6450): 1 of byte[] (320 elements)
06-07 16:33:04.377 W/dalvikvm( 6450): 1 of byte[] (1024 elements)
06-07 16:33:04.377 W/dalvikvm( 6450): 1 of byte[] (1612 elements)
06-07 16:33:04.377 W/dalvikvm( 6450): 1020 of short[] (160 elements) (1020 unique instances)
06-07 16:33:04.377 W/dalvikvm( 6450): 1 of char[] (17 elements)
06-07 16:33:04.377 E/dalvikvm( 6450): Failed adding to JNI pinned array ref table (1024 entries)
……
06-07 16:33:04.387 E/dalvikvm( 6450): VM aborting
06-07 16:33:04.387 F/libc ( 6450): Fatal signal 6 (SIGABRT) at 0x00001932 (code=-6), thread 7290 (Thread-274)
之後在網上查了下,說這個問題是引用計數器溢位了,最大為1024,看了JNI層的程式碼,我是建立了兩個short陣列,之後在迴圈中處理short陣列中的資料,但是之後並沒有釋放掉,程式碼如下:
jshort *in1;
jshort *out1;
jint Index;
if(!env || (Length <= 0))
return;
in1 = (*env)->GetShortArrayElements(env, in, 0);
out1 = (*env)->GetShortArrayElements(env, out, 0);
Index = 0;
do {
_reduce(&NPP_Channel[0], &in1[Index], &out1[Index], (Length>NR_MAX_FRAME_SIZE)?NR_MAX_FRAME_SIZE:Length);
Length -= NR_MAX_FRAME_SIZE;
Index += NR_MAX_FRAME_SIZE;
}while (Length > 0);
解決辦法是在迴圈結束之後,將陣列釋放掉,程式碼如下:
//使用完之後要釋放掉資源,否則會出現ReferenceTable overflow 異常
(*env)->ReleaseShortArrayElements(env, in, NULL,0);
(*env)->ReleaseShortArrayElements(env, out, NULL,0);
/**void GetShortArrayRegion (jshortArray val0, jsize val1, jsize val2, jshort * val3)
*引數含義:表示把陣列val1從第val個元素開始的val2個元素拷貝到val3地址所指向的記憶體區域
*/
新增上面的兩行程式碼之後,程式執行正常。
參考資料: Android NDK之JNI陷阱