jvm垃圾收集

判断对象是否已死

        有两种方法,一种是引用计数法,另一种是可达性分析算法。前一种无法解决循环引用的问题,所以这里主要介绍第二种。所谓可达性分析算法,就是找一些GC Roots节点,当从这些节点出发遍历对象,没有遍历到的认为需要被回收。但是也不是绝对的,当GC Roots节点不可达时,还要经过两次标记才能最终确定是否被回收。当GC Roots不可达时,即被第一次标记并判断是否要执行finalize方法。判断标准是,如果对象没有重写finalize方法或者finalize方法以及被jvm调用过一次,那么认为没有必要执行finalize方法。如果被判断需要执行finalize方法,则要将其放入F-Queue队列里。随后jvm虚拟机对齐再次标记。当发现仍然没有被引用指向时,则确定回收。在加载类即编译器就要记录引用的位置,以方便扫描。

垃圾收集算法

主要有四种垃圾收集算法:
标记-清除算法:会产生碎片
复制算法:jvm把新生代分为三部分:Eden区和两个Survivor区,比例是8:1:1。当给对象分配内存时,优先使用Eden区,然后是其中一个Suvivor区。当需要进行Minor GC(发生在新生代区,与此对应的是发生在老年代区的full GC)时,要把存活的对象复制到另一个未使用的Suvivor区里,然后对Eden区和另一个Suvivor区进行清理。之所以不分成两个相同的区域,是为了扩大内存利用率(如果只有两个区域,那就闲置了一半的空间)。
        应当注意的是,Suvivor区并不一定能装下所有存活的对象,这个时候就需要老生代去做空间分配担保。即在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象空间,如果条件成立,那么Minor GC是安全的。如果不成立,则要看HandlePromotionFailure设置值是否允许担保失败,如果允许,会继续检查老年代最大可用连续空间是否大于历次晋级到老年代对象的平均大小,如果大于,将尝试着进行一次Minor GC,尽管是有风险的(如果担保失败,会进行一次GC)。如果小于或者设置HandlePromotionFailure不允许担保失败则进行一次full GC。
标记-整理算法:主要用于老生代垃圾收集,不会产生碎片。
分代收集算法:将java堆划分为新生代和老年代,采用不同的算法。因为新生代里的对象大部分都是朝生夕死的,而老年代里的对象存活时间要长很多。

一个虚拟机里GC收集器不是唯一的,下面列举一些主要的GC收集器:Serial收集器(仍然使用较多,单线程)、CMS(多线程,支持与用户线程并发)、G1(最新版本,也支持与用户线程同步执行)。不同的GC收集器主要是在是否是单线程、是否支持与用户线程一起执行方面有差别。当支持与用户线程一起运行时,会产生浮动垃圾,即垃圾回收过程中用户线程执行产生的垃圾,这部分垃圾只能下次回收了。另外即使支持与用户线程一起运行,也不是绝对的,只不过"stop the world"的停顿时间很短。


下面介绍新生代的对象怎么转移到老生代:

大对象直接进入老年代,比如大数组(因此在设计程序时应该避免使用存活短的大对象)。
长期存活的对象将进入老年代:每Minor GC一次,在新生代里的对象年龄长1,当达到阈值时移入老年代
动态年龄判定:即满足在Survivior空间中相同年龄所有对象大小的总和大于Survivor空间的一半时,年龄大于或等于该年龄的对象就可以直接进入老年代。

当程序到达安全点或者安全区域会触发GC

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值