频繁点击一个按钮,程序崩溃,查看log部分详情如下:

04-1111:10:40.371:W/dalvikvm(5507):ReferenceTableoverflow(max=1024)04-1111:10:40.371:W/dalvikvm(5507):JNIpinnedarrayreferencetable(0x6242b008)dump:04-1111:10:40.371:W/dalvikvm(5507):Last10entries(of1024):04-1111:10:40.371:W/dalvikvm(5507):1023:0x42e97298int[](456elements)04-1111:10:40.371:W/dalvikvm(5507):1022:0x41c16618int[](69elements)04-1111:10:40.371:W/dalvikvm(5507):1021:0x42e5ef28byte[](1280elements)04-1111:10:40.371:W/dalvikvm(5507):1020:0x4230da28byte[](119elements)04-1111:10:40.371:W/dalvikvm(5507):1019:0x422a03f0byte[](14elements)04-1111:10:40.371:W/dalvikvm(5507):1018:0x42efced0byte[](1920elements)04-1111:10:40.371:W/dalvikvm(5507):1017:0x422bc570byte[](119elements)04-1111:10:40.371:W/dalvikvm(5507):1016:0x41f52e68byte[](14elements)04-1111:10:40.371:W/dalvikvm(5507):1015:0x423c41d0byte[](119elements)04-1111:10:40.371:W/dalvikvm(5507):1014:0x422b8bf0byte[](14elements)04-1111:10:40.371:W/dalvikvm(5507):Summary:04-1111:10:40.371:W/dalvikvm(5507):20ofbyte[](12elements)(20uniqueinstances)04-1111:10:40.371:W/dalvikvm(5507):1ofbyte[](13elements)04-1111:10:40.371:W/dalvikvm(5507):489ofbyte[](14elements)(489uniqueinstances)04-1111:10:40.371:W/dalvikvm(5507):1ofbyte[](68elements)04-1111:10:40.371:W/dalvikvm(5507):3ofbyte[](69elements)(3uniqueinstances)04-1111:10:40.371:W/dalvikvm(5507):486ofbyte[](119elements)(486uniqueinstances)04-1111:10:40.371:W/dalvikvm(5507):10ofbyte[](148elements)(10uniqueinstances)04-1111:10:40.371:W/dalvikvm(5507):10ofbyte[](152elements)(10uniqueinstances)04-1111:10:40.371:W/dalvikvm(5507):1ofbyte[](1280elements)04-1111:10:40.371:W/dalvikvm(5507):1ofbyte[](1920elements)04-1111:10:40.371:W/dalvikvm(5507):1ofint[](69elements)04-1111:10:40.371:W/dalvikvm(5507):1ofint[](456elements)04-1111:10:40.371:E/dalvikvm(5507):FailedaddingtoJNIpinnedarrayreftable(1024entries)04-1111:10:40.371:I/dalvikvm(5507):"main"prio=5tid=1RUNNABLE


主要问题是ReferenceTable overflow 。查看资料,发现是引用计数器溢出了,最大为1024.即java的内存管理机制是基于引用的,需要计数器来记录引用的次数。在overflow这句话下面dump出了最近的10个引用,Summary下面可以看出有哪些引用。可以发现其中有两组byte[],每组的引用达到480多次。我恍然大悟,每点击一次按钮,引用一次,下次点击时上次的资源未被释放。于是一直累加直至计数器溢出。

检查代码发现:

intnArrLen_u=env->GetArrayLength(jbUrl);if(nArrLen_u>0){pUrl=(char*)malloc(nArrLen_u+1);bzero(pUrl,(nArrLen_u+1));jU=env->GetByteArrayElements(jbUrl,NULL);memcpy(pUrl,jU,nArrLen_u);}intnArrLen_x=env->GetArrayLength(jbXml);if(nArrLen_x>0){pXmlBuf=(char*)malloc(nArrLen_x+1);bzero(pXmlBuf,(nArrLen_x+1));jX=env->GetByteArrayElements(jbXml,NULL);memcpy(pXmlBuf,jX,nArrLen_x);}


代码上可以看出我调用了两次 GetByteArrayElements 但是却没有释放掉。所以在最后添上释放语句就解决了~


if(nArrLen_u>0){env->ReleaseByteArrayElements(jbUrl,jU,0);}if(nArrLen_x>0){env->ReleaseByteArrayElements(jbXml,jX,0);}

参考Android NDK之JNI陷阱在用到NewByteArray类似方法时一定要DeleteLocalRef(),使用GetByteArrayElements时 要用ReleaseByteArrayElements来进行释放。

问题就是答案!真正明白是什么问题之后,也就找到了答案。