今天调试一个小工程,工程运行一段时间后就自动关闭或者重启,严重的时候直接就是模拟器关闭或者重启了。很是无奈哇……
把Log调出来看了下,发现报出了Excessive JNI global references的错误。
在网上找解决办法,可是网上对这个问题的讨论并不多,最多的就是有人问了,BUT,没有人来答呀……
后来重复运行那个工程好几次,发现Log中会一直追踪打印如下信息:
GREF has increased to 301
GREF has increased to 501
GREF has increased to 601
GREF has increased to 801
GREF has increased to 1101
.
.
GREF has increased to 1501
.
.
后来了解到是因为vm对jni层的reference有个数限制,过多很造成VM aborting。因此每次在GREF增加到2000以上的时候就直接aborting了……
在纠结2h后,找到了原因:
是我在工程的一个方法中有数据库的查询动作,也就是用到了cursor,而我并没有在查询动作完成后释放掉cursor,更悲催的是,我在一个runnable中相当相当频繁的调用这个定义了cursor的方法,SO……就这样华丽丽的崩溃了哇>_<
找到原因后,加上cursor.close();来释放这个cursor。再运行工程后,追踪Log如下:
GREF has increased to 301
GREF has decreased to 199
GREF has increased to 301
GREF has decreased to 199
GREF has increased to 301
GREF has decreased to 199
.
.
可以看到,现在的GREF 就 一直维持在两三百之间,这个应该说是就很safe的啦~~嘿嘿……补充一点哈~
就简单的看代码的话,那个cursor变量并不是什么GREF哇,也就一个局部的变量,方法结束了也就在适当的时候被回收了呀,为什么会引起Excessive JNI global references的错误呢?
其实,在数据库查询时那个cursor是代表的一个流,接受从数据库中读出的信息,虽然方法结束后那个变量是没用了,但是这个流并没有关闭,一直被程序保留,也就成了GREF的积累,造成最终的Excessive JNI global references错误了哈~
还有,也有可能因为其他各种原因造成Excessive JNI global references的错误,反正大家如果遇到这样的问题就先去查看代码中有没有什么没有释放的变量,对象或者流啊什么的,一定一定要记得及时释放资源,这样也能提高程序的效率哇~
以上也就是针对这个问题的一点点很肤浅的理解,也仅是希望能帮助大家解决类似的问题,如果有人能深入了解这个问题的原因,也请给大家分享下哦^_^~