java基础-垃圾收集器及其回收算法的介绍


前言

       最近在刷面试题的时候会经常遇到关于java垃圾收集器的问题,所以开此博文来介绍一下垃圾收集器以及有关的算法。具体的内容可以查阅《深入理解Java虚拟机-周志明》,下面的有关内容也是引自这本书。


一、垃圾收集器管理的区域

       Java虚拟机会将所管理的内存进行划分,划分为:程序计数器、虚拟机栈、本地方法栈、堆、方法区。其中,堆(几乎所有对象都在此分配内存)是垃圾收集器管理的内存区域。

二、垃圾收集器的回收步骤

1.阶段一:判断对象是否存活

  1. 引用计数器算法(主流JVM不使用):每个被管理的对象与一个引用计数器相关联,该计数器记录着该对象当前被引用的次数,当次数为0时则可以判断此对象死亡。之所以主流的JVM不使用,是因为此算法很难解决对象之间相互循环引用的问题。
  2. 可达性分析算法:利用的是树的结构来判断对象是否存活。树的根称为“GC Roots”。要判断一个对象是否存活,就从根节点出发向下搜索,看能不能找到这个对象,如果不能找到说明此对象不再使用,进行第一次标记。

2.阶段二:筛选

       阶段一完成后还不能马上进行垃圾回收,还需要对标记的对象进行一次筛选。以“这个被标记的对象是否有必要执行finalize方法”为筛选条件筛选出要回收的对象。若对象没有覆盖finalize方法或者finalize方法已经被虚拟机调用过,则不会执行finalize方法回收对象。否则将对象放置在F-Queue队列中,稍后虚拟机会建立低调度优先级的Finalizer线程去执行对象的finalize方法。等待过程中出现死循环或者执行缓慢或导致F-Queue其他对象永久等待,这时对象可能不会被回收,gc将会进行第二次小规模的标记,如果对象重新与引用链上的任何对象建立关联,会移出“即将回收”的集合,否则会真的被回收。

三、垃圾收集算法

1.分代收集理论——理论基础

  1. 弱分代假说:绝大多数对象都是朝生夕灭的
  2. 强分代假说:熬过越多次的垃圾收集器过程的对象就越难以消亡
  3. 跨分代引用假说:跨代引用相对于同行引用来说仅占极少数
    根据弱分代假说以及强分代假说可以知道需要将堆分成不同区域:新生代、老年代。新生代里的对象都会大批“死去”,老年代则相反。
    根据跨分代引用假说可以知道应该建立“记忆集”来记录老年代中的哪一块内存存在跨代引用。

2.标记-清除算法

       步骤:首先标记所有要回收的对象,在标记完成后统一回收掉所有被标记的对象即可。
       缺点:效率低,如果标记的对象是离散分布的,则会存在大量的碎片。
       现在的JVM都不采用此算法,但这个算法却是其它算法的基础。

3.标记-复制算法

       步骤:将内存按容量大小划分为大小相等的两块,每次只使用其中的一块,当这一块的内存用完了,就将还存在着的对象(未被回收的对象)复制到另一块内存上,然后再把已使用过的内存空间一次清理掉。
       缺点:如果内存中大多数对象是存活的,会产生大量的复制操作,可用内存缩小一半。
       如果内存中的对象绝大多数都是朝生夕灭的,那么就不会频繁的发生复制操作,降低复制开销。根据前面提到的堆划分为新生代以及老年代,很容易就能发现此算法适合回收新生代里的对象。
       现代商用Java虚拟机大多都优先采用标记-复制算法去回收新生代里的对象。
       但上面的算法还是不够理想,故提出了其改良版:Appeal式回收:
       步骤:将内存划分为一块较大的Eden空间和两块较小的Survior空间,每次分配内存只使用Eden和其中一块Survior,发生垃圾收集时,将Eden和Survior中仍存活的对象一次性复制到另外一块Survior空间,然后直接清理掉Eden和已使用过的Survior。当Survior空间不能容纳一次新生代垃圾收集之后存活的对象,就需要依赖其它内存区域(例如老年代)进行分配担当。至于Survior以及Eden空间应该怎么分配大小,各个虚拟机有不同的分配原则。

4.标记-整理算法

       标记-整理算法针对老年代区域。
       步骤:算法与标记-清理算法类似,不同之处在于清除时让所有空存活的对象都向同一端移动,然后直接清理掉边界以外的内存。
       由于针对的是老年代,此区域的对象只有极少数的对象需要回收,所以不需要花大量的移动的操作。

四、补充

       垃圾回收器线程的优先权最低。垃圾回收器监视对象,当一个对象长时间不使用时,GC会在空闲时期(不定时)对对象进行回收,释放内存空间,可以使用System.gc()方法建议GC进行回收,只是一个建议而已,所以GC不一定会执行。Java的GC可以有效防止内存溢出,但是不能保证不会出现内存溢出。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喂喂,要加油

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值