垃圾回收算法与分代机制

对象已死的判定

引用技术算法:

        在对象中添加一个引用计数器,每当一个新的引用指向对象时就将引用计数器+1,当引用失效时就-1,最后为0的就是垃圾。引用计数法有着明显的缺陷,当出现以下相互引用的代码时由于A和B相互引用了一次,引用计数器永远不会置零,则堆中将存在无法被回收的垃圾。

User A = new User();
User B = new User();

A = B;
B = A;
 
A = null;
B = null;

可达性分析算法

        Java采用的是可达性分析算法,基本思路是通过一系列Gc Roots的跟对象作为启示节点集,根据这个节点开始向下进行引用关系搜索,搜索所走过的路径为引用链,如果某个对象到到Gc Root 没有引用链则表示这个对象为垃圾。

        在Java体系中可作为Gc Roots的对象分别:虚拟机栈中的引用对象、方法区中静态属性引用对象、常用引用对象、本地方法栈中native方法引用对象、Java虚拟机中一些常驻的异常对象、类加载器、同步锁持有对象、反应Java虚拟机内部情况的JMXBean、JVMTI中注册回调和本地代码缓存等。

        即使可达性算法判定对象是垃圾,对象也不是非死不可。要判定一个对象死亡最多会进行两次标记,没有与Gc Roots 连接的引用链为第一次标记,随后进行一次筛选,筛选条件为此对象是否有必要执行finalize方法,加入对象没有覆盖finalize方法,或者此方法已经被调用,那么虚拟机将这两种情况都视作没必要清理。

        如果这个对象被判定需要执行finalize方法,那么该对象会被放置在一个名为F-Queue的队列中,稍有由一条低优先级的Finalizer线程去运行。如果对象想要自救,需要在finalize方法中与Gc Roots 重新建立引用链。对象只能自救一次,因为任何一个对象的finalize方法都只有被调用一次,下一次回收finalize不回再次执行。

分代理论假说

弱分代假说:绝大多数对象都是朝生夕灭的

强分代假说:熬过越多次垃圾回收的过程的对象就越难消亡

对象的年龄通过熬过垃圾回收的次数决定

        Java垃圾回收器应该将堆划分出不同的区域,依照对象的年龄进行存储。如果一个区域的对象都是新生代对象朝生夕灭,每次回收只考虑保存少量的对象,而不是去标记大量需要回收的对象。如果一个区域的对象是老年代对象,那么应该采用较低的频率来回收这块内存区域,同时兼顾垃圾收集时间开销和空间有效利用。

标记清楚算法 

        首先标记处所有要回收的对象,在回收过程中统一回收标记的对象,当然也可以反过来。

        缺点:效率步稳定,会产生大量的空间碎片

标记复制算法

        将可用内存划分为大小相等的两块,每次只使用其中一块,当一块内存使用完后将存活对象复制到另一块内存区域,再将已使用的内存清理。一般不在老年代使用。

        缺点:内存只能使用一半,空间浪费,暂停用户线程

标记整理算法

        与标记复制算法前置相同,不过不进行复制而是将清理后的空间碎片向一段进行整理。

        缺点:暂停用户线程,操作负重大

        每种回收方法都有一定的缺陷,此外还有一种和稀泥的解决方案,平时采用标记清理,定期采用标记整理进行垃圾回收。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值