Java的内存泄漏和垃圾回收机制

Java的垃圾回收(Garbage Collection,GC)机制是JVM提供的重要功能之一,能够自动检测对象是否已经没有任何引用,
从而自动释放不在使用的对象所占用的内存空间,避免引发内存泄漏,但是该机制并不能完全避免内存泄漏情况的发生。

1. 内存泄漏

定义:指由于疏忽或错误造成程序未能释放已经不再使用的内存,即由于不再使用的对象持续占用内存或者占用的内存得不到及时释放,造成内存空间浪费,从而降低计算机的性能。
原因:当长生命周期对象持有短生命周期对象的引用时,就很有可能造成内存泄漏,尽管短生命周期对象已经不再需要,
但是由于长生命周期对象仍有它的引用,从而导致短生命周期对象所占用的内存不能被及时回收,造成内存泄漏。
常见的例子:

  • 静态集合类引起的内存泄漏:在使用ArrayList、Vector等的时候,如若把它们声明为static,则它们的生命周期就和类一样长,它们所引用的对象不能被及时释放;
  • 监听器:在释放对象的时候如果没有相应的删除其监听器,就有可能造成内存泄漏;
  • 连接:Java中的各种连接包括数据库连接、网络连接和IO连接,如果没有显示调用其close()方法进行关闭,这些连接就不会被回收从而造成内存泄漏;

2. GC算法

1. 根搜索算法:程序把所有的引用关系看作一棵树,从根节点GC Root开始寻找相应的引用节点,
如果找到这个节点,则继续寻找该节点的引用节点,当所有的引用节点寻找完毕,剩下的节点就被认为是无用节点,
其占用的内存会被回收,该算法用于判断对象是否存活,如下所示:

这里写图片描述

Java中常见的可作为GC Root的对象有:静态变量引用的对象和常量引用的对象。

根搜索算法可以判定对象是否存活,在标记出存活对象和可回收对象后,基于其标记、回收行为,GC算法有以下算法:

2. 标记-清除算法:先暂停整个程序的全部运行线程,让回收线程以单线程进行标记,并进行清除回收,完成后恢复运行线程。

这里写图片描述

缺点:这样会导致大量零碎的空闲空间碎片,不容易获得连续的大容量内存空间,从而降低内存利用率。

3. 标记-整理算法:与上述算法类似,不同的是会先把所有存活对象搬运汇集到连续的内存空间,然后清理掉另一端的可回收对象,从而集成空闲空间。

4. 复制算法:程序将所拥有的可用的内存空间分成两部分,对象先存储在一部分,同样暂停整个程序的全部运行线程,
进行标记后,将存活对象搬运汇集到另一个部分中,然后把使用过的这块内存中的可回收对象清理掉,
在下一次GC周期中,两部分内存的角色对调,依次使用这两块内存。

这里写图片描述

需要搬运移动的算法的缺点:对于存活时间长、大容量的储存对象需要耗费更多的移动时间。

5. 分代收集算法:理解该算法需要了解JVM中”运行时数据区”的划分(可参考: Java虚拟机基础知识汇总 (二) )。
程序运行所需的存储对象会先存放在新生代,新生代中的对象存活率低,所以该区域会发生较为频繁的垃圾回收行为,
每次回收完成幸存的存储对象内的寿命计数器加1,当新生代的存储对象的寿命计数器达到一定阈值时,
则被移动到年老代,老年代中的对象存活率高,所以该区域会有较少的垃圾回收行为。
因此新生代可以选择复制算法或标记-整理算法,因为存活对象少、搬运移动成本低,而老年代可以采用标记-清除算法。

参考链接:http://blog.csdn.net/jfkidear/article/details/9034881
https://zh.wikipedia.org/wiki/,感谢作者~

这里写图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值