jvm垃圾收集器详解

1. 简介

垃圾收集器虽然从Serial -> Parallel->ParNew->CMS->G1->ZGC一步步演化,但是新的垃圾收集器不一定就适合所有场景,从垃圾收集的发展进程的可以看出,垃圾收集器的演化无非因为一下几点:

  • 贴合当下的硬件,能够更友好的使用硬件资源
  • 减少STW(Stop The World)的时间,提高用户体验

2. 基本概念

2.1 jvm内存模型

  • 本地方法栈: native方法
  • 栈:一个方法对应一块栈帧内存空间,主要存储局部变量表、操作数栈、动态链接、方法出口
  • 程序计数器:每一个栈都有自己的程序计数器,用户恢复现场
  • 堆:内存分配和垃圾回收的主要场所
  • 方法区:运行时常量池,主要存储元空间、常量、静态变量、类信息

2.2 对象内存分配流程

  • 对象逃逸分析:当一个对象在方法中被定义后,没有被外部方法引用
    • 方法内部的对象,可以直接分配在栈的,但是太大了也只能放在堆中
    • 如果对象不会逃逸可以将该对象在栈上分配内存,这样该对象所占用的内存空间就可以随栈帧出栈而销毁,就减轻了垃圾回收的压力
    • 栈上分配依赖于逃逸分析和标量替换
  • 标量替换:标量指不可被进一步分解的量,而JAVA的基本数据类型就是标量
    • 确认对象不逃逸,将对象的成员变量拆分成若干个被这个方法使用的成员变量替换

2.2 垃圾查找算法

  • 引用计数法: 效率高,无法解决循环引用的问题(基本不用)
  • 可达性分析法:将“GC Roots” 对象作为起点,从这些节点开始向下搜索引用的对象,找到的对象都标记为非垃圾对象,其余未标记的 对象都是垃圾对象
  • 根节点(root)
    • 线程栈的本地变量
    • 静态变量
    • 本地方法栈的变量

2.3 垃圾收集算法

  • 分代收集理论
    • 根据存活周期不同将内存分为几块
    • 新生代每次收集都会有大量的对象死亡(一般采用复制算法)
    • 老年代的对象存活的几率比较大(一般采用标记整理或者标记清除)
  • 复制算法:将内存分为大小相同的两块,每次使用一块,当一块内存使用完后,就将还存活的对象复制到另一块,清理掉当前的块内存
    • 优点:不会产生内存碎片,效率高
    • 缺点:内存被分割为两份,占用内存较多
  • 标记清除算法:标记存活的对象,清除没有被标记的对象(会造成大量的内存碎片,最后肯定会进行一次整理算法)
    • 优点:内存占用低
    • 缺点:效率不高,容易使内存碎片化
  • 标记整理算法:标记存活的对象,让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存
    • 优点:内存占用低
    • 缺点:效率不高,比清除算法还要低,清除算法会将多次碎片内存进行一次整理

3. 垃圾收集器

  • 黑色相连: 表示可以相互配合使用
  • 红色相连:表示在最后可能会转变成另外一种方式回收

3.1 Serial

3.2 Parallel

3.3 ParNew

3.4 CMS

3.5 G1

3.6 ZGC

posted @ 2021-10-28 12:09  雾里看花的少年  阅读(128)  评论(0编辑  收藏  举报