JVM面试_6

垃圾回收算法分类:

  1. 标记-清除算法
  2. 复制算法
  3. 标记-整理算法

标记清除算法

顾名思义,该算法进行垃圾回收共分为两个阶段:

  1. 标记:根集合出发,进行扫描,通过可达性算法需要回收的对象进行标记.

这里有的地方说的是对存活的对象进行标记,其实也有道理,不过书上说的是对需要回收的对象,那就写需要回收的对象

  1. 清除: 对堆内存从头到尾进行线性遍历,回收不可达对象内存.
    在这里插入图片描述

标记清除算法的不足:

  1. 由于标记-清除算法不需要进行对象的移动并且仅对不存活的对象进行处理,所以回收后,会产生很多不连续的碎片化的空间,这就有可能导致较大的对象没有足够的内存存放,因此不得不提前触发另一次垃圾回收.
  2. 效率比较低.

复制算法

  • 可用的内存按容量及一定比例划分为两块, 并选择其中一块作为对象面,另一块作为空闲面.
  • 对象在对象面上创建.
  • 对象面的内存用完之后,就将存活的对象从对象面复制到空闲面.
  • 将对象面的所有对象内存全部清除.
  • 这种方法适用于对象存活率较低的场景.
  • 移动的时候,只需要移动堆顶指针,按顺序分配内容即可.
    在这里插入图片描述

复制算法的好处:

  1. 由于每次是对一整个区域进行回收,所以不会产生不连续的碎片化的空间.
  2. 移动的时候直接顺序分配内存,简单高效.
  3. 年轻代的垃圾回收主要通过这种算法.

标记-整理算法
当复制算法在对象存活率比较高的时候就要进行较多的复制操作,效率就会变低,而且,如果不想五五开这样浪费50%的空间的话,就需要额外空间进行担保,防止空闲面的内存不够存活对象放的情况,因此,老年代不采用这种算法,老年代采用标记-整理算法.


标记-整理算法过程:

  1. 标记: 从根集合进行扫描,通过可达性分析算法,对存活的对象进行标记.
  2. 清除: 清除时移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收.
    在这里插入图片描述

标记-整理算法好处:

  1. 解决了碎片化空间的问题.
  2. 不需要像复制算法一样设置两块内存.
  3. 适合于对象存活率较高的场景.

分代收集算法(主流GC算法)

分代收集算法可以认为是垃圾回收算法的组合拳
它将堆内存进行进一步的划分,按照对象生命周期的不同来划分区域以采用不同的垃圾回收算法.
这样的目的就很简单: 用于提高JVM的回收效率.

一般来说,年轻代存活率低,就采用复制算法,老年代存活率高,就采用标记-清除算法或者标记-整理算法.


GC的分类
分代收集算法的GC主要有两种:

  1. Minor GC: 也就是发生在年轻代的垃圾收集动作,所采用的的是复制算法,年轻代几乎是所有java对象出生的地方, 即java对象申请的内存以及对象的存放都在这里进行.
  2. Full GC: 该GC与老年代相关,由于对老年代的回收一般会伴随着年轻代的垃圾收集,因此它才被称为Full GC.

JDK7及其之前的堆内存分布图:
在这里插入图片描述
由图可知,JDK7及以前,堆内存可以分为三个部分: 年轻代,老年代,永久代.


JDK8及其以后的堆内存分布图:
在这里插入图片描述
如图所示: JDK8及其以后,由于没有了永久代,所以堆内存就只有两部分了:年轻代,老年代.


年轻代

年轻代中存放的都是那些朝生夕灭的对象,所以它会尽可能快速地收集掉那些生命周期短的对象,主要包括三个区域:

  • Eden区: 伊甸园啊~~~,所以说我们就可以知道对象刚被创建出来的时候,都是被放在Eden区的,当然了,Eden放不下了还是有可能放在Survivor区的.
  • 两个Survivor区(from区, to区): 这两个区域不是固定的,会随着垃圾回收相互转换.
  • 三个区域的比例如图:
    在这里插入图片描述
    在年轻代中,每次它都只会使用Eden区和其中的一块Survivor区(一般认为是From Survivor区)用来存放对象,当进行GC的时候,它就把这两个区域里存活的对象全部都放到另一个Survivor区域(To Survivor区)中去,然后一次性清除掉之前的Eden区和From Survivor区,最后交换两个Survivor区的身份,将From Survivor当作To Survivor区,同时注意:当survivor区域的内存不足以存放所有的存活对象的时候,就会往老年代中放.

老年代

老年代中存放的一般都是生命周期较长的对象,采用标记-清除算法或者标记-整理算法进行垃圾回收.
由于对老年代的回收一般会伴随着年轻代的垃圾收集,也就是说会对整个堆进行回收,所以它被称为Full GC或Major GC.

Full GC比Minor GC慢,但是执行频率较低.

触发Full GC的条件

  1. 老年代空间不足.
  2. CMS GC(并发标记-清除算法)时出现promotion failed(minor gc时survivor中放不下了,对象要放到老年代,同时此时老年代也放不下), concurrent mode failure.
  3. Minor GC晋升到老年代的平均大小大于老年代剩余空间.
  4. 调用System.gc(),此时会提醒虚拟机要对老年代和新生代进行回收,但是具体啥时候回收,要不要回收还是由虚拟机决定.

对象如何晋升到老年代

  1. 经历一定的Minor GC次数之后依然存活的对象(对象在新生代每经历一次Minor GC,它的年龄计数器就会加1,一般年龄计数器到15了就会进入老年代).
  2. Survivor区中存放不下的对象会直接进入老年代.
  3. 新生成的大对象直接进入老年代中(-XX: +PretenuerSizeThreshold控制大对象的大小,超过该值的就直接进入老年代).

常见的调优参数:
在这里插入图片描述
比如当值设置为8的时候,就表示Eden与其中一个Survivor的比例为8:1.
在这里插入图片描述
比如当值设置为2的时候,那么老年代的内存和年轻代内存的比例为2:1.
新生代和老年代所占内存的总大小是通过-Xmx和-Xms决定的.
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值