1. 程式人生 > >JNI使用過程中出現的ReferenceTable overflow問題

JNI使用過程中出現的ReferenceTable overflow問題

工作中,在使用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陷阱