GC基础理论知识

Java GC

java垃圾回收器自动回收,没有任何引用链接的就是垃圾

如何确定垃圾

引用计数法:记录引用计数,为0就是垃圾,但是无法解决循环引用找不到垃圾问题
根可达算法:没有同GC roots链接的,都是垃圾
GC基础理论知识_第1张图片

垃圾清除算法

Mark-Sweep 标记清除,算法相对简单,两遍扫描(扫描一遍存活的,再扫描一遍未存活的)效率偏低,容易产生碎片,所以不适合eden区。存活对象比较多的情况下效率较高

Copying 拷贝,分为两块内存,将有用的拷贝到另一块内存。空间浪费,移动复制对象,需要调整对对象的引用。适用于对象存活比较少的情况,只扫描一次,效率提高,没有碎片。适用于eden区

Mark-Compact 标记压缩,算法相对复杂,两遍扫描,需要移动对象,效率偏低。不会产生碎片,方便对象分配,不会产生内存减半

GC算法基础概念

因为根对象有可能已经到了old区,所以由于做YGC时,需要扫描整个OLD区,效率非常低,所以JVM设计了CardTable, 如果一个OLD区CardTable中有对象指向Y区,就将它设为Dirty,下次扫描时,只需要扫描Dirty Card
在结构上,Card Table用BitMap来实现

堆内存逻辑分区(适用于分代的垃圾回收器,从ZGC开始不再分代了)

GC基础理论知识_第2张图片
新生代,老年代1:2
1、新new出来的对象,首先尝试栈上分配,栈上分配不下放到eden区。
2、经过一次垃圾回收后,仍然存活,放到survivor区。再经过一次垃圾回收后,仍然存活,放到另一个survivor区,同时eden区存活的对象也放到这个survivor区里。
3、当来回再survivor区的次数超过15次后,进入老年代。(对象mark word 分代记录4字节,锁两个自己 )

新生代、老年代是堆内,永久代是堆外
永久代(1.7)Perm Generation/ 元数据区(1.8) Metaspace 是Method Area 方法区的实现

  1. 永久代 存放 元数据 - Class
  2. 永久代必须指定大小限制 ,元数据区可以设置,也可以不设置,无上限(受限于物理内存)
  3. 字符串常量 1.7放于永久代,1.8 放于堆中
  4. MethodArea逻辑概念 - 1.7叫Perm Generation, 永久代、 1.8叫MetaSpace 放于元数据区(放置除了Class之外的其他信息,jit)

分代及相关参数设置

GC基础理论知识_第3张图片
-Xmn:设置年轻代大小
-Xms:最小内存,-Xmx:最大内存

栈上分配和线程本地分配

GC基础理论知识_第4张图片

栈上分配(不需要垃圾回收,弹栈就消失了,效率较高)

无逃逸:逃逸分析其实就是分析一个方法中创建出来的‘对象’的作用域是否限制于本方法内。

public void test(){ new hello(); }//没有逃逸
Hello h; public void test(){ h = new hello(); }//逃逸了

支持标量替换:调用时不反回对象类型,而是返回一个基础数据类型

-XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:-UseTLAB 关闭逃逸分析,标量替换,线程本地分配

对象何时进入老年代

GC基础理论知识_第5张图片

记忆点,除CMS是6,其他的都是15

动态年龄:当survivor区在互相拷贝时,发现该survivor区+eden,超过自身的一半了,将年龄最大的放到老年代中
分配担保:YGC期间 如果仍然发现survivor区空间不够了 空间担保直接进入老年代

对象分配总结

GC基础理论知识_第6张图片

1、实例化之后,看能否放到栈中,可以放到栈中,弹出结束
2、不能放到栈中,看对象大小,如果大,放到老年代,Full/major GC结束
3、如果不大,看能否放到线程本地分配中,最终放到eden区
4、GC算法执行,未存活,minor/young GC结束。存活的s1,s2区来回复制,年龄大放到OLD区,

全部的垃圾回收器

GC基础理论知识_第7张图片
垃圾回收器的成长历程

JDK诞生 Serial就有了。为了提高效率,诞生了PS。为了配合CMS,诞生了PN,CMS是1.4版本后期引入,CMS是里程碑式的GC,它开启了并发回收的过程,但是CMS毛病较多,因此目前任何一个JDK版本默认是CMS
并发垃圾回收是因为无法忍受STW
垃圾回收器的成长与服务器内存大小有很大关系:
1、serial 几十兆 可以处理
2、PS 上百兆~几个G 可以处理
3、CMS 20G
4、G1 上百G
5、ZGC 4T

Serial 单线程
Parallel 多线程
Young
Serial,ParNew,Parallel Scavenge
Old
CMS,Serial Old,Parallel Old

常见组合
Serial + Serial Old
Parallel Scavenge+Parallel Old
ParNew+CMS

垃圾回收器详述

串行

GC基础理论知识_第8张图片

Serial:年轻代 串行回收
a stop-the-world,copying collector which uses a single GC thread。
在需要垃圾回收时,并且处于safe point 可以执行STW时,进行STW。GC开始
设计解释:
当时的虚拟机内存比较小,单线程STW的时间不会很长,单机而现在的内存比之前要比之前大的多了,STW时间变得很长,不满足需求了

Serial Old:老年代 串行回收
a stop-the-world,mark-sweep-compact collector that uses a single GC thread

并行

GC基础理论知识_第9张图片

生产环境未作任何调优,默认就是ps+po

parallel Scavenge:PS 年轻代 并行回收
a stop-the-world,copying collector which uses multiple GC threads

parallel old:PO 老年代 并行回收
a compacting collector that uses multiple GC threads

并发垃圾回收,垃圾回收和应用程序同时运行,降低STW时间

GC基础理论知识_第10张图片

ParNew paralle new,Paralle Scanvenge的增强,年轻代 配合CMS的并行回收,默认线程数为CPU核数

  • a stop-the-world,copying collector whitch uses multiple GC threads
  • It differs from “parrallel Scavenge” in that it has enhancements that make it usable with CMS
  • For example,“ParNew” does the synchronization needed so that it can run during the concurrent phases of CMS
    (ParNew和Paralle Scanvenge比较)
    PN响应时间优先,为了配合CMS。PS吞吐量优先

GC基础理论知识_第11张图片

CMS :ConcurrentMarkSweep 老年代 并发的,垃圾回收和应用程序同时运行,降低STW的时间(200MS)
CMS有一些问题,所以没有任何版本默认是CMS的,只能手工指定。CMS是MarkSweep,必然会导致碎片,当碎片到一定程度,CMS老年代分配对象分配不下时,使用serialold进行老年代串行回收。
会产生浮动垃圾
解决方案:降低触发CMS的阈值,保持老年代有足够的空间
-XX:CMSInitiatingOccupancyFraction 92% 降低百分比

六个阶段
预处理阶段
初始标记:STW,标记出根对象。因为只标记跟对象,所以很快
并发标记:标记垃圾,浪费80%GC时间,同应用程序一同运行
重新标记:STW,并发处理中产生了新的垃圾,或者有一些垃圾重新被使用,不再是垃圾。因为大部分垃圾在并发标记时处理过了,所以也很快。
并发清理:将产生的垃圾清除掉,但是同时也会产生新的垃圾。也就是浮动垃圾,这种浮动垃圾只能等待下一个垃圾回收进行处理
整理阶段

三色标记,并发标记时的算法

CMS使用的是三色标记+Incremental Update算法
G1使用的是三色标记+snapshot at the begining (SATB)算法
ZGC: Colored Pointers+写屏障
Shenandoah :Colored Pointers+读屏障

GC基础理论知识_第12张图片

你可能感兴趣的:(JVM)