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