讲讲Java的垃圾回收机制

如何判断该对象是否是‘垃圾’?

  1. 引用计数算法

给对象添加一个引用计数器,每当一个地方引用它时计数器的值+1,引用失效计数器值-1。当计数器为0的时候该对象就是不可被使用的。

优点:实现简答、效率简单

缺点:无法解决对象之间的相互循环引用的问题

  1. 可达性分析算法(根搜索算法)

通过叫GC Roots的对象作为根节点,向下检索,检索到的对象被视为可达性对象,即非垃圾,检索的路径成为引用链。而当一个对象到GC Roots没有任何引用链的时候即视为‘垃圾’

GC Roots对具体包括:

  1. 虚拟机栈栈帧中本地变量表中引用的对象

属于执行上下文中的对象,线程在执行方法的时候,会把方法打包成一个栈帧入栈执行。方法中的局部变量会存放在其本地变量表中。只要方法未结束,没有出栈,意味着这些对象还会被访问。GC就不应该回收。

  1. 方法区中静态属引用的对象

全局对象的一种,Class对象本身很难被回收,回收的条件非常苛刻,只要Class对象不被回收,静态成员就不会被回收

  1. 方法去中常量引用的对象

全局变量的一种,常量本身被初始化之后不会改变,因此可作为GC Roots

  1. 本地方法栈中JNI(即Native方法)引用的对象

和虚拟机栈栈帧中本地变量表中引用的对象作为GC Roots的原理类似

  1. 被同步锁持有的对象

如果当前线程持有对象锁,GC如果回收了,对象锁就生效了,所以不行

虽然方法区的静态属性引用的对象和常量引用的对象都可以作为GC Roots,但是永久代也是可以进行垃圾收集的,在永久代中主要回收:废弃常量和无用的类两部分。

--回收废弃常量的原理和回收堆中的对象类似。

--判断无用的类相对来说比较复杂,必须满足三条件:

--该类的实例是否全部都已经被回收,也就是Java堆中不存在该类的任何实例

--加载该类的ClassLoader已经被回收

--该类对应的Class对象没有在任何地方引用,无法在任何地方通过反射去访问该类的方法

finalize方法

在真正宣告一个对象死亡时至少要经过两次标记过程,如果对象在进行根搜索后发现该对象没有与GC Roots的引用链,那么此时就会被标记一次并且进行一次筛选。筛选条件是该对象是否覆盖finalize方法,如果未覆盖且未执行,那么会被判定有必要执行,该对象会被放置在一个名为F-Queue的队列之中,然后会由虚拟机自动建立的低优先级的线程去执行覆盖后的方法。如果没有覆盖或者已经执行该方法,则被视为“没有必要执行”

垃圾回收算法

  1. 标记-清除算法

标记所有需要回收的对象,在标记完成后统一回收所有被标记的对象

缺点:效率不高、内存碎片化,碎片如果太多当需要分配较大对象时无法找到足  够的连续内存而不得不触发另一个垃圾回收

  1. 标记-复制算法

将内存等分分为两块,每次只使用其中一块,当这一块内存使用完时,就将存活的对象复制到另一边,然后把可回收对象全部清除

  1. 标记-整理算法

把所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存

  1. 分代收集算法

根据对象的存货周期的不同将内存划分为多块,一般是新生代(少量存活对象)、老年代(大量存活的对象,必须标记清除标记整理)。然后根据各代特点去采用适合的收集算法

常见的垃圾回收器

  1. Serial收集器

单线程收集器,优点:简单高效,没有线程交互的开销

缺点:当它运行的时候,其他工作线程必须暂停。

  1. ParNew收集器

Serial所线程版本

  1. Parallel Scavenge收集器

‘标记-复制’,并发多线程收集器。其目标达到可控制的吞吐量,高吞吐量可以高效的利用CPU时间,使用于在后台运算而不用太多的交互任何

  1. CMS收集器

基于‘标记-清除’以获得最短回收停顿时间为目标的收集器,重视服务的响应速度。运行过程分为4阶段:

--初始标记,标记GC Roots直接关联到的对象

--并发标记,标记引用链上的对象

--重新标记,因用户线程和收集器并发运行,所以可能会有标记产生变动的可能, 所以这个阶段进行修正并发标记

--并发清除

缺点:

无法处理浮动垃圾:并发清理时,用户线程并发运行,如果此时产生了新垃圾时,此时收集器无法再本次收集过程中处理,只能留给下一次GC

可能出现‘Concurrent Mode Failure’失败:在垃圾回收期间,用户线程还需要运行,则还需要预留充足的空间给用户线程使用。如果预留空间无法满足系统需要时,就报该错误。启用后备方案,临时启用Serial Old收集器重新对老年代进行垃圾收集

  1. G1收集器

基于‘标记-整理’算法实现的收集器,并不会产生内存碎片。可以精确的控制停顿,可以让使用者规定在某一时间段,垃圾收集的时间不得超过某一时间。

G1收集器将整个Java堆划分为多个大小固定的独立区域,并且追踪每个区域的立即堆积程度,在后台维护一个优先列表,每次根据使用者规定的时间内优先去回收垃圾堆积程度最大的区域

参考于《深入理解Java虚拟机》

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值