java中不存在内存泄漏_关于Java内存泄漏

Java中由于有垃圾收集器(GC)自动回收资源,所以一般情况下不需要担心内存泄漏的问题。这也是Java相对C/C++而言开发简单高效的重要原因之一。想必调试过C/C++内存泄漏障害的人都深有体会。但是如果认为Java中不存在内存泄漏也是不对的。因为GC不是万能的,也有它失灵的时候。那它什么情况下会失灵呢?先简单了解一下GC的工作方式吧。

垃圾收集器每过一段时间就会将不再使用的资源回收。GC判断一个对象是否是不再使用的方法非常重要。它以每个活的线程对象为根检查有没有能够到达目标对象的引用链为判断标准。如果不可达则说明该对象对程序(或者线程)的执行是不可见的,因为没有任何手段可以引用该对象,自然这个对象肯定是不再被使用了。于是将其回收。

简单思考一下,上面的判断逻辑只是“什么是不使用对象”的充分条件,而不是必要条件。至于必要条件是什么,答案只有开发者自己知道,因为只有开发者自己才能准确知道哪些对象已经确实不再需要了,GC又怎么能揣测到开发者的意图呢?

理解了这一点我们就知道了Java内存泄漏的第一种模式:GC不能正确识别出不再使用的对象。既:存在一条以活的线程对象(通常是主线程)为起点的引用链,指向了已经不再使用的对象。并且这些对象在程序运行中未能及时释放后者数目不断增长导致内存消耗过大(如果内存消耗能始终保持在可接受的范围之内,就谈不上什么内存泄漏了)。这样的内存泄漏通常发生在一个集合对象上,尤其是作为高速缓存使用的集合对象。

本来我以为刚才提到的模式是Java内存泄漏唯一的一种模式,但是一次实际经历使我看到了第二种Java内存泄漏的模式:GC不能正常释放它想释放的对象。这是由于用户重载了某个Java对象的finalize()方法,GC在释放这个对象时就要调用这个被修改了的finalize()方法,而这个finalize()方法又由于某个原因离奇地无法结束(比如等待某个同步对象或者发生了死循环*),也就导致这个对象没法被正常释放,于是内存泄漏自然就发生了。当然这种情况比起前面提到的第一种模式要少见的多。

* 我遇到的情况是finalize()方法在等待一个同步对象,但是该同步对象又被别的线程长时间霸占着。这个线程虽然也有释放同步对象,但这个线程循环执行并且垃圾收集的线程优先级比较低,所以释放了的同步对象很快又被它抢了去。并且这个线程在执行过程中又会创建新的修改了finalize()方法的Java对象,导致该Java对象虽然也能被释放,但释放的速度跟不上创建的数据,时间久了,内存消耗就会越来越大,内存泄漏也就发生了。

阅读(2801) | 评论(0) | 转发(0) |

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值