Jvm的三大算法
GC是什么?频繁收集Young区、较少收集Old区、基本不动Perm区 [ 掌握 ]
1>. GC的总体概述
JVM在进行GC时,并非每次都对上面三个内存区域一起回收的,大部分时候回收的都是指新生代。因此GC按照回收的区域又分为两种类型:一种是普通GC(minor GC) ,一种是全局GC (major GC or Full GC)
①. 普通GC(minor GC):只针对新生代区域的GC
②. 全局GC(major GC or Full GC):针对老年代的GC,偶尔伴随对新生代的GC以及对永久代的GC
2>. 复制算法 [ 谁空谁是to,复制要交换 ]
- 重点记忆部分[ 掌握 ]
新生代中使用的是Minor GC ,这种GC算法采用的是复制算法(Copying)
优点:不会产生内存碎片,且对象完整不丢
缺点: 浪费了10%的空间
- 复制算法的原理
HotSpot JVM 把年轻代分为了三部分:1个Eden 和 2个Survivor 区(别名叫from和to)。默认比例为8:1:1,一般情况下,新创建的对象都会被分配到Eden(一些大对象特殊处理),这些对象经过第一次Minor GC 后,入伙仍然存活,将会被移动到Survivor 区。对象在Survivor区中每熬过一次Minor GC ,年龄就会增加1岁,当它的年龄增加到一定程度时,就会被移动到老年代中。因为年轻代中的对象基本都是朝生夕死(80%以上),所以在年轻代的垃圾回收算法使用的是复制算法,复制算法不会产生内存碎片
在GC开始的时候,对象只会存在于Eden区和名为“From” 的Survivor 区,Survivor 区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenurin gThreshold 来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候回,“From”和“To”会交换他们的角色,也就是新的“To” 就是上次GC前的 “From”,新的“From”就是上次GC前的"To" .不管怎样,都会保证名为To的Survivor区域是空的。Minor GC 会一直重复这样的过程,直到 “To”区被填满,“To”区被填满之后,会将所有对象移动到老年代中
3>. 标记清除(Mark-Sweep) 和 标记整理(Mark-Compact)
老年代 一般是由标记清除或者是标记清除与标记整理的混合实现
3.1. 标记清除(Mark-Sweep)
优点:不需要额外的空间[ 掌握 ]
缺点:①.两次扫描,耗时严重 ,会产生内存碎片 ②.清理出来的空闲内存不连续 ③.效率低[ 掌握 ]
首先,它的缺点就是效率比较低(递归与全堆对象遍历),而且在进行GC的时候,需要停止应用程序,这会导致用户体验非常差劲
其次,主要的缺点则是这种方式清理出来的空闲内存不连续的,这点不难理解,我们的死亡对象都是随机的出现在内存的各个角落,现在把它们清除之后,内存的布局自然会乱七八糟
- 标记(Mark)
从根结合开始扫描,对存活的对象进行标记
2. 清除(Sweep)
扫描整个内存空间,回收未被标记的对象,试用free-list记录可以区域
3. 动态图
3.2>. 标记整理(Mark-Compact)
- 原理
- 动图
先把存活的对象进行标记,然后整理
4>. 复制算法、标记清除算法、标记整理算法的比较
内存效率:复制算法>标记清除算法>标记整理算法(此处的效率只是简单的对比时间复杂度,实际情况不一定如此)
内存整齐度: 复制算法=标记整理算法>标记清除算法
内存利用率:标记整理算法=标记清除算法>复制算法