垃圾收集(Garbage Collection):通常被称为"GC",由虚拟机"自动化"完后垃圾回收工作
1.前言
上一章讲解的JVM内存结构,知道程序计数器是唯一没有OutOfMemoryError的区域,堆是垃圾回收的主要区域,本章继续学习JVM相关知识,了解Java GC的底层原理
2.目录
目录3.GC垃圾回收机制
JVM中程序计数器,虚拟机栈,本地方法栈3个区域随线程而生随线程而灭,栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动的内存清理.它们的内存分配和回收都具有确定性.因此,GC垃圾回收主要集中在堆和方法区,运行期间,内存的分配和回收都是动态的
3.1.判断对象存活
可达性分析法
- 常规方法分:引用计数法和可达性分析法
- 引用计数法:给每个对象添加一个引用计数器,每当引用它时计数器加1,引用释放时减1,为0时可以回收(java虚拟机没有使用,没有解决循环引用的问题)
- 可达性分析法:GC Root对象(如系统类加载器,栈中的对象,处于激活状态的线程)作为起点,向下搜索,与其相连的存活,没有任何一条与GC Root相连的不可用
3.2.垃圾回收算法
3.2.1.标记清除算法
编辑清除算法
- 包含"标记"和"清除"两个阶段,首先标记所有需要回收的对象,标记完成后统一回收
缺点:标记和清除效率不高,标记清除后会产生大量不连续的内存碎片,后续对象需要较大内存时会应无法找到足够的连续内存空间而提前触发垃圾收集动作
3.2.2.复制算法
复制算法
- 将内存容量划分为大小相等的两块,只使用其中的一块,没有足够内存空间时,将还存活的对象复制到另一块,然后清理掉这一块的内存
堆内存分配结构图
- 优势:对半回收时,内存分配不用考虑内存碎片的情况,只需移动堆顶指针,按顺序分配内存即可,简单,高效
- 劣势:可用内存缩小为1半,性价比低,新生对象存活率高时,复制工作效率低
- GC过程中,当Eden区满时,还存活的对象会复制到其中的一个Survivor区(如果Survivor区没有足够的内存时,会进入老年代),回收时会将Eden和Survivor区还存活的对象,复制到另一个Survivor区,然后清理Eden和用过的survivor区
- 在GC的整个过程中,由于Eden是对象创建和回收的主要区域,所以采用8:1:1的比例来分配内存;对象每经历一次复制,年龄加1,达到晋升年龄的阈值后转移到老年代(老年代采用的是标记整理算法)
3.2.3.标记整理算法
标记整理算法标记过程与"标记清除算法"一样,然后让所有存活的对象都向一端移动,然后清理掉边界外的内存
这算法既没有浪费50%的内存,也不会因对象存活率高导致效率低下(老年代采用该算法)
3.2.4.分代收集算法
将Java的堆内存逻辑上分为两块,新生代和老年代,针对不同的存货周期,不同大小的对象采用不同的垃圾回收策略
新生代中大多数对象的存活时间都是瞬间的,只有少量对象存活,复制少量对象即可完成清理,即采用复制算法
老年代中的对象存活率高,也不需要额外的而辅助内存,因此采用标记整理算法
3.3.垃圾收集器
Java7和Java8默认使用的是Parallel,Java9和Java10使用的是G1
3.3.1.Parallel收集器
- 新生代使用复制算法
- 老年代使用标记整理算法
- -XX:+UseParallelGC,使用Parallel收集器+老年代串行
-
-XX:+UseParallel收集器+老年代并行
Parallel收集过程
3.3.2.GMS收集器
GMS收集过程
- Concurrent Mark Sweep 并发标记清除(应用线程和GC线程交替执行)
- 使用标记清除算法
- 并发阶段会降低吞吐量(停顿时间减少,吞吐量降低)
- 老年代收集器(新生代使用ParNew)
- 1.初始标记(会产生全局停顿)-根可以直接关联到的对象,速度较快
- 2.并发标记(和用户线程一起)-标记过程,标记全部对象
- 3.重新标记(会产生全局停顿)-并发标记时,用户线程依然运行,正式清理前,再做修正
- 4.并发清除(和用户线程一起)-基于标记结果,直接清理对象
3.3.3.G1收集器
最新前沿成果之一,将替换掉JDK1.5中的CMS收集器
- G1收集器的运作大致可划分为以下几个步骤:初始标记(Initial Marking),并发标记(Concurrent Marking),最终标记(Final Marking),筛选回收(Live Data Counting and Evacuation),与CMS流程很相似
- 使用G1收集器时,Java堆的内存布局与其他收集器有很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔阂了,它们都是一部分(可以不连续)Region的集合
4.总结
JVM有良好的的自动内存管理机制,但在某些极端情况下也许开发者妥善处理,方便JVM更好的管理内存.学习此章只需结合场景理解不同的收集算法即可,都是些概念方面的知识点
参考博客:
https://www.choupangxia.com/2019/10/20/interview-jvm-gc-01/
https://www.choupangxia.com/2019/10/25/interview-jvm-gc-03/
网友评论