GC什么样对象需要被回收?垃圾回收算法有哪些?如何选择垃圾回收器?如何选择?

都知道Java垃圾回收都是交给JVM来处理,什么时机、如何处理了解不多,可以查看此篇文章。如果了解,浏览文章一起交流。分为三个模块:什么样对象需要回收?回收算法有哪些?如何选择垃圾回收器?

java中有了垃圾自动回收机制,让程序员更多的关注业务,不必考虑内存的释放。所以自动垃圾算法就变的很重要了,
如果算法不合理,导致一些内存不释放,从而就导致内存溢出。

一 什么样对象需要被回收?

垃圾回收机制通过一套的有效的算法计算,什么对象有效,什么对象无效。对于无效的对象进行回收。
常见的计算对象的有效无效两种方法:引数计数法、可达性分析算法。

备注:
    计算对象是否有效算法和收集垃圾算法是两回事。计算对象是否有效之后,进行对象对象回收的
    算法(垃圾回收算法)。

1.1 引数计数法

1. 原理

假设一个对象a,被引用一次,那么a应用计数器会加1。引用失败时,a计算器减1。
当a的计数器的值为0,说明对象a没被引用,可以被回收。

2. 优缺点
优点:

回收的及时性高,因为不会等到内存不足来回收对象,直接根据对象的计数器为0进行回收。
在垃圾回收过程中,应用无需挂起。
区域性,在更新计数器只会影响该对象,不会扫描全部对象。

缺点:

每次对象应用,去更新计数器,有一点时间开销。
无法解决循环引用。

1.2 可达性分析算法(重点)

一系列称为“GC Roots”的根对象作为起始节点集。如果某一个对象到节点集没有引用,则称该对象不可达,
可以被回收。

在这里插入图片描述

1. 在虚拟机中被成为GC Roots对象有哪些?(了解)
a 虚拟机栈中的引用对象。
b 方法区中,静态属性引用对象。
c 方法区中,常量引用对象。
d 本地方法栈中JNI引用对象。
e 同步锁持有对象
f Java虚拟机内部的引用。

2. 对象的引用
强引用:不会被回收。

软引用:内存发生泄漏之前,会进行二次回收。如果这次回收没有足够内存,抛出内存溢出异常。

弱引用:活到下一次垃圾回收为止。

虚引用:无法通过一个虚引用获取对象,虚引用唯一目的就是,对象被回收时,收到一个系统通知。

二 垃圾回收算法有哪些?

2.1 标记清除

1. 原理
分为两个阶段,标记和清除。
标记:从根节点标记被引用对象。
清除:未被标记的对象为垃圾对象,可以被清理。

在这里插入图片描述

2. 缺点
执行效率低,在GC需要停止应用程序。而且在标记和清除都需要对所有对象便利。
内存碎片化计较严重,因为无效的对象被收集,内存不连续,收集后,可用内存变
成一片一片。

2.2 标记压缩

1. 原理
也是先标记引用对象。然后将被引用对象压缩到内存一边。然后将边界外的对象全部清理。

在这里插入图片描述

2. 优缺点
解决内存碎片化。但是增加了元素的移动步骤,效率依旧很低。

2.3 标记复制

1. 原理
将原有的内存一分为二,每次只用其中的一块内存。在垃圾回收时,将正在使用的对象复制到
另外一个内存空间,然后将这部分空间清空。交换两个内存空间角色。

在这里插入图片描述

2. 适用场景
需要复制对象很少的场景。

3. JVM年轻代内存空间

在这里插入图片描述

a 在GC开始,对象只会存在Eden和Servivor的From区,Servivor的To区为空。
b 紧接着GC,Eden区对象复制到To,From区的对象根据阙值来决定去向。达到阙值到老年区,没达到阙值到To区。
c 经过这次GC,Eden和From区被清空。From和To交换角色。
d GC一直重复这样的动作,直到To被填满,所有对象移到老年代。

4. 优缺点
优点:内存无碎片化,垃圾对象多效率高。
缺点:垃圾对象少,不适用。两块内存,一个时刻,只能用一半,效率低。

2.4 分代算法

1. 原理
将短暂存活的对象放在一起,进行高频率回收。将长久存活的对象放在一起,进行低频率回收。
分代算法根据对象的特点进行选择。在jvm中,年轻代适合复制算法,老年代适合标记清除和标记压缩。

2. 垃圾回收相关概念
部分收集:

    新生代收集:只是新生代垃圾收集
    老年代收集:只是老年代垃圾收集
    混合收集:整个年轻代和部分老年代收集

整堆收集:

    Full GC

三 垃圾回收器有哪些?如何选择?

jvm中实现各种垃圾回收器:串行垃圾回收、并行垃圾回收、CMS垃圾回收器、G1垃圾回收期、ZGC垃圾回收器。

在HotSpot虚拟机中,常见虚拟机组成方式:

在这里插入图片描述

3.1 串行垃圾回收器

1. 原理
单线程进行垃圾回收,在回收的时候,只有一个线程工作,Java应用所有的线程暂停,
等待垃圾回收完成。这种现象成为STW。

2. 设置垃圾回收器为串行收集器
-XX:+UseSerialGC 指定年轻代和老年代都使用串行垃圾收集器 。
-XX:+PrintGCDetails 打印垃圾回收的详细信息

# 为了测试GC,将堆的初始和大内存都设置为16M 
-XX:+UseSerialGC -XX:+PrintGCDetails -Xms16m -Xmx16m
在这里插入图片描述

3.2 并行垃圾回收器

1. 原理

多个线程进行垃圾回收。减少回收时间。

2. 设置并行垃圾回收器(ParNew垃圾收集器)

#参数,将老年代改为并行收集器,年轻代还是串行收集器
 -XX:+UseParNewGC -XX:+PrintGCDetails -Xms16m -Xmx16m

3. ParallelGC垃圾收集器
ParallelGC收集器工作机制和ParNewGC收集器一样。只是在这个基础上增加两个参数。

在这里插入图片描述

#参数,年轻代和老年代都使用了ParallelGC垃圾回收器。 
-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:MaxGCPauseMillis=100 -XX:+PrintGCDetails Xms16m -Xmx16m

3.3 CMS垃圾回收器

是标记清除算法的垃圾回收器,该回收器适合老年代回收器。

1. CMS垃圾回收执行原理

在这里插入图片描述

2. 设置垃圾回收器:

#设置启动参数 
-XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -Xms16m -Xmx16m

3.4 G1垃圾回收器(重点)

在jdk7中使用的全新的垃圾处理器。oracle官方计划在jdk9中将G1变成默认的垃圾收集器, 以替代CMS。 

1. G1环境下,JVM性能调优:
a 开启G1垃圾回收器
b 设置堆最大内存
c 设置最大停顿时间
备注:
G1提供三种垃圾回收机制,Young GC、Mixed GC和Full GC,在不同的条件触发。

2. 原理:
取消老年代和年轻代物理上的划分,取而代之是将堆分成若干区域(Region),包含逻辑上的年轻代和老年代。

Humongous区域:
当一个对象占用空间超过分区50%,G1认为是一个巨型对象。巨型对象默认放到老年代,如果巨型对象生命
周期较短,会对垃圾回收器造成负面影响。

G1划分了一个Humongous,专门用于存放巨型对象。如果一个H装不下一个对象,G1会找连续的H空间来存
储。为了找连续的H区,会引起Full GC。

Region的大小通过参数-XX:G1HeapRegionSize设定,取值范围为为1MB~32MB,且是2的N次方。

2. Young GC:

主要是对Eden区进行GC,在Eden区被耗尽时会触发。
Eden区空间中的对象移动到Survivor空间,如果Survivor空间不够会移动到老年代空间。
Survivor区数据移动到Survivor区中,也有部分数据移动到老年代。
Eden区空间为空,GC停止,应用程序继续。

Remembered Set:
因为GC年轻代对象时候,需要找到对应的跟对象。跟对象可能在年轻代和老年代。
为了避免全局扫描引入RSet。

每个Region初始化会初始化一个RSet,该集合用于存储其他Region指向该Region对象的引用。

在这里插入图片描述

3. Mixed GC:

越来越多的对象晋升到老年代,虚拟机触发一个混合垃圾回收器。回收整个整个Young区,和部分老年代对象。 

什么时候触发MixedGC:

 -XX:InitiatingHeapOccupancyPercent=n 决定。默认:45%,该参数的意思是: 当老年代大小占整个堆大小百分比达到该阀值时触发MixedGC。

GC步骤:
全局并发标记:

在这里插入图片描述

拷贝存活对象:
在这里插入图片描述

4. G1收集器参数设置:
在这里插入图片描述

-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:+PrintGCDetails -Xmx256m

3.5 ZGC垃圾回收器

ZGC是JDK11加入具有实验性质低延迟的垃圾回收器。在尽可能对吞吐量影响不大的前提下,在任意堆内存
大小都可以把垃圾回收时间限制在10毫秒以内。

1. 内存布局:

ZGC的内存为Page(道理和Region一样)具有动态性--动态创建和销毁,以及动态的区域容量大小。在X64硬件平台
Page具有大中小三类容量。

小型页面固定大小为2MB,放小于256kb的小对象。

中型页面固定大小为32MB,大于等于256k小于4MB的对象。

大型页面容量不固定,可以动态变化,必须是2MB整数倍,用于放大于等于4MB对象。

2. 性能表现:

虽然稳定性和调优在不断的进行。但是ZGC在吞吐量和延迟性依旧很亮眼。
在以低延迟的目标下ZGC已经达到了高吞吐量为目标的目标Parallel Scavenge的99%。
在延迟方面,ZGC毫不留情与Parallel Scavenge、G1拉开了两个数量级的差距。

3. 使用:

环境必须以JDK11的条件下。

命令:

#执行命令 
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx256m -Xlog:gc*=info TestGC
 
#参数说明
 -XX:+UnlockExperimentalVMOptions 解锁实验参数 
 -XX:+UseZGC  启用ZGC垃圾收集器 
 -Xmx256m  设置大内存 
 -Xlog:gc*=info  设置打印gc日志信息
 
#设置并行的线程数,一般默认即可 
-XX:ConcGCThreads  

4. 染色指针技术:

在这里插入图片描述

染色指针指针技术使用剩下的46位指针宽度,将高4位提取出来,作为标志。通过标志位,虚拟机可以从指针看到其
引用对象的三色标记、是否进入从分配、是否通过finalize()方法才能被访问到。

染色指针的好处:

在这里插入图片描述

染色指针工作过程:
在这里插入图片描述
在这里插入图片描述

四 可视化日志分析

将GC日志进行可视化分析。

1. 日志打印出来参数设置:

-XX:+PrintGC 输出GC日志
-XX:+PrintGCDetails 输出GC的详细日志 
-XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式) 
-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息 
-Xloggc:../logs/gc.log 日志文件的输出路径

demo

-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -Xmx256m -XX:+PrintGCDetails XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC Xloggc:F://test//gc.log
 
#ZGC 在jDK11下执行,参数有所不同 
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx256m -Xlog:gc*:gc.log TestGC

2. 打开网址,上传日志文件:

https://gceasy.io/
在这里插入图片描述
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容