【基础篇】十四、GC算法

文章目录

  • 1、实现思路
  • 2、SWT
  • 3、GC算法
  • 4、标记清除算法Mark Sweep GC
  • 5、复制算法Copying GC
  • 5、标记整理算法
  • 6、分代算法Generational GC
  • 7、分代的整体流程

1、实现思路

Java实现垃圾回收的步骤:

  • 根据GC Root对象可达性分析,将内存中对象标记为存活的、可回收的
  • 处理可回收的对象,释放空间在这里插入图片描述

2、SWT

GC是在一个单独的线程,但不管JVM用哪种算法,都会存在一个阶段需要停止所有的用户线程,称Stop The World(STW),SWT大,用户用起来自然卡。

在这里插入图片描述

感受下SWT:

public class StopTheWorld {public static void main(String[] args) {/*** 启动用户线程和GC线程* 查看不同阶段用户线程的执行时间*/new PrintTimeThread().start();new ClearThread().start();}
}/*** 模拟用户代码,这里直接打印这段代码的执行耗时*/
class PrintTimeThread extends Thread {@SneakyThrows  //lombok的try..catch@Overridepublic void run() {long begin = System.currentTimeMillis();while (true) {long now = System.currentTimeMillis();System.out.println(now - begin);begin = now;Thread.sleep(100);}}
}/*** 模拟GC线程*/
class ClearThread extends Thread {@SneakyThrows@Overridepublic void run() {List<byte[]> list = new LinkedList<>();while (true) {//存80个100M后就删除里面byte对象的强引用,垃圾回收释放if(list.size() >= 80){list.clear();}list.add(new byte[1024 * 1024 * 100]);Thread.sleep(100);}}
}

添加JVM参数,使用分代回收的垃圾回收器,输出GC详细信息,并限制堆最大10G:

-XX:+UseSerialGC -Xmx10g -verbose:gc

运行发现用户线程本来100ms左右的事儿,有时候会被拖到2000ms以上:

在这里插入图片描述

3、GC算法

对象回收算法的评价标准:

  • 吞吐量 = 执行用户代码时间 /(执行用户代码时间 + GC时间),值越大,性能越高
  • 最大暂停时间:SWT的最大值

在这里插入图片描述

  • 堆的使用效率:如复制算法只用一半空间

在这里插入图片描述

以上三个指标,不可兼得。各个算法各有长处,对应着不同的适用场景。

4、标记清除算法Mark Sweep GC

实现:

  • 从GC Root List开始,遍历引用链,找到可达对象,并标记
  • 清除没标记的对象

在这里插入图片描述

优点:

  • 实现简单,只需给对象维护个标记位

缺点:

  • 导致内存碎片化:从原本连续的内存空间,摘掉一些被回收的,得到一些碎片。如下回收了4+3+2,却连个5字节的对象都创建不了

在这里插入图片描述

  • 分配速度慢:由于内存碎片化,需要维护一个空闲链表记录可用空间,新对象来了每次都得往后遍历,找出一块合适大小的地儿安置

在这里插入图片描述

5、复制算法Copying GC

实现:

  • 堆内存一分为二,一半叫From,一半叫To
  • 新对象来了往From安置
  • GC时,把From的存活对象Copy到To

在这里插入图片描述

  • 清掉From,From和To名字互换,原来的To做为新的From安置新new的对象

完整例子:

  • 开始状态:

在这里插入图片描述

  • GC开始,把GC Root对象和可达的对象搬到To空间
    在这里插入图片描述

  • 清掉From空间,并把原来的To改为From空间
    在这里插入图片描述

一句话:将存活的对象搬运到另一块空间,清理掉当前空间,互换名字

优点:

  • 解决了内存碎片化:往To搬的时候,按连续地址往过码
  • 吞吐相比下面的标记整理算法要高:只需遍历一次存活对象。但不如标记-清除算法,因为后者不用给对象搬家

缺点:

  • 堆内存使用率低:安置新对象只能用50%的堆空间,另一半得留着To

5、标记整理算法

也称标记压缩,用来解决标记清除算法的内存碎片化缺点。

实现:

  • 从GC Root开始,遍历标记可达对象
  • 将可达的存活对象移动到堆的一端,清掉非存活的

在这里插入图片描述
优点:

  • 无内存碎片化问题:比标记清除多了一步整理
  • 堆内存利用率比复制算法高

缺点:

  • 理解阶段性能不高,得看整理阶段的实现算法

6、分代算法Generational GC

组合使用了上面的几种算法,被主流使用。分代即把内存分为年轻代和老年代:

在这里插入图片描述

关于这几块空间的大小设置:

在这里插入图片描述

Demo:

public class Gc {@SneakyThrowspublic static void main(String[] args) {List<Object> list = new ArrayList<>();int count = 0;while (true) {System.in.read();System.out.println(++count);list.add(new Byte[1024 * 1024]);}}
}

对应JVM的参数:

-XX:+UseSerialGC -Xms60m -Xmn20m -Xmx60m -XX:SurvivorRatio=3 -XX:+PrintGDetails

粗略计算:老年代60m - 20m = 40m,Eden除以随便一块s区 = 3,则Eden:s0:s1 = 12:4:4,使用阿尔萨斯执行memory验证:

在这里插入图片描述

7、分代的整体流程

  • 新new的对象,安置到堆的年轻代的伊甸园区

在这里插入图片描述

  • 伊甸园区满了以后,触发GC,仅是年轻代的GC(Minor GC、Young GC)
  • 把Eden的存活对象放入S1(To),Eden区被清空(复制算法)

在这里插入图片描述

  • 互换名,S0做为To,S1做为From,再安置新对象,直到Eden和From满

在这里插入图片描述

  • 再次触发Minor GC,Eden和From存活对象放入S0,其余清掉回收(每次GC能活下来的,记录年龄,+1)

在这里插入图片描述

  • 对象GC年龄到达阈值(最大15,对象头里放着,默认值和垃圾回收器有关),晋升到老年代。(一直活着就别在From和To之间来回搬了)

在这里插入图片描述

  • 老年代最后也满了,新new的对象进来,先Minor GC,还是不足,再Full GC,对整个堆进行垃圾回收,此时的STW时间就比Minor GC时的SWT长一些了

在这里插入图片描述

  • Full GC后,无法回收老年代对象,再往老年代放,就OOM

在这里插入图片描述
补充:如果现在新生代已经满了,Minor GC还是满,再来对象,尽管新生代有的对象没到达年龄阈值,也会被搬到老年代

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/322978.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【python入门】day18:文件、os相关操作

编码格式 1、ASCLL–ISO8859-1–GBK–UTF-8– ISO8859-1–GBK等文件在格式上会显示为ASCLL 2、python文件默认格式 utf-8,看格式流程 选择python文件–用记事本打开–另存为… 这时可看到该文件的格式 3、修改python文件默认编码格式&#xff0c;在文件开头添加上&#xff1a; …

Docker容器相关操作

文章目录 容器相关操作1 新建并启动容器2 容器日志3 删除容器4 列出容器5 创建容器6 启动、重启、终止容器7 进入容器8 查看容器9 更新容器10 杀掉容器11 docker常用命令汇总 容器相关操作 ​ 容器是镜像的运行时实例。正如从虚拟机模板上启动 VM 一样&#xff0c;用户也同样可…

分布式【Zookeeper三大核心之数据节点ZNode】

ZooKeeper在分布式领域&#xff0c;能够帮助解决很多很多的分布式难题&#xff0c;但是底层却只是依赖于两个主要的组件&#xff1a;ZNode文件/数据存储系统和watch监听系统&#xff0c;另外还有一大模块&#xff0c;就是ACL系统。本节我们介绍下znode文件/数据存储系统。 一、…

uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -后端架构搭建

锋哥原创的uniapp微信小程序投票系统实战&#xff1a; uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…

VuePress部署到GitHub Pages

一、git push自动部署 1、创建用于工作流的文件 在项目根目录下创建一个用于 GitHub Actions 的工作流 .yml 文件 name: docson:# 每当 push 到 main 分支时触发部署push:branches: [main]# 手动触发部署workflow_dispatch:jobs:docs:runs-on: ubuntu-lateststeps:- uses: a…

Python-CSV文件的存储

CSV文件存储 CSV其文件以纯文本形式存储表格数据。CSV文件是一个字符序列&#xff0c;可以由任意数目的记录组成&#xff0c;各种记录由某种换行符分隔开。它比Excel文件更加简洁&#xff0c;XLS文本是电子表格&#xff0c;包含文本、数值、公式和格式等内容&#xff0c;CSV中则…

安装extiverse/mercury时报错

问题描述 作者在安装 Flarum 的插件 extiverse/mercury 时报错&#xff0c;内容如下图所示 解决方案 ⚠警告&#xff1a;请备份所有数据再进行接下来的操作&#xff0c;此操作可能会导致网站不可用&#xff01; 报错原因&#xff1a;主要问题是在安装过程中解决依赖关系。具…

vue项目使用vue-pdf插件预览pdf文件

1、安装vue-pdf&#xff1a;npm install --save vue-pdf 2、使用 具体实现代码&#xff1a;pdfPreview.vue <template><div class"container"><pdfref"pdf":src"pdfUrl":page"currentPage":rotate"pageRotate&qu…

提升办公效率:掌握批量文件重命名的技巧

在日常生活和工作中&#xff0c;经常要处理大量的文件&#xff0c;如文档、图片、音频等。在这些情况下&#xff0c;会遇到要批量重命名文件的情况。如果一个一个地重命名&#xff0c;不仅耗时&#xff0c;而且效率低下。今天来讲解一些技巧通过批量重命名文件&#xff0c;从而…

【springboot+vue项目(零)】开发项目经验积累(处理问题)

一、VUEElement UI &#xff08;一&#xff09;elementui下拉框默认值不是对应中文问题 v-model绑定的值必须是字符串&#xff0c;才会显示默认选中对应中文&#xff0c;如果是数字&#xff0c;则显示数字&#xff0c;修改为&#xff1a; handleOpenAddDialog() {this.dialogT…

Android中的Intent

一.显式Intent 显示Intent是明确目标Activity的类名 1. 通过Intent(Context packageContext, Class<?> cls)构造方法 2.通过Intent的setComponent()方法 3.通过Intent的setClass/setClassName方法 通过Intent(Context packageContext, Class<?> cls)构造方法 通…

【bug】【VSCode】远程终端TERMINAL打不开

【bug】【VSCode】远程终端TERMINAL打不开 可能的原因现象分析解决 可能的原因 昨天晚上vscode在打开多个TERMINAL的情况下&#xff0c;挂了一晚上&#xff0c;今早上来看的时候全都lost connections…。然后关闭再打开就出现了如上现象。 早上一来到实验室就要debug… 现象…