8.GC基本原理

目录

  • 概述
  • 垃圾回收
    • 引用计数法 (Reference Counting)
    • 根可达分析算法 (GCRooting Tracing)
    • 对象引用类型
      • 强引用
      • 软引用
      • 弱引用
  • 清除垃圾
    • 1.标记-清除算法 (Mark-Sweep)
    • 2.复制算法 (Copying)
    • 3.标记-整理算法 (Mark-Compact)
    • 分代回收 (Generational Collection)
  • 垃圾回收器
    • GC-串行收集器
      • Serial与SerialOld
    • 并行收集器
      • Parallel Scavenge (Stop)
      • Parallel Old
      • ParNew
      • CMS
      • Garbage-First (G1)
        • G1内存划分
      • ZGC
  • 结束

概述

相关文章在此总结如下:

文章地址
jvm基本知识地址
jvm类加载系统地址
双亲委派模型与打破双亲委派地址
运行时数据区地址
运行时数据区-字符串常量池、程序计数器、直接内存地址
jvm中对象创建流程与内存分配地址
jvm对象内存布局地址

垃圾回收

垃圾回收是必须的,不然 jvm 内存很快就会满。
没有被引用的对象,称之为垃圾对象

垃圾对象查找方式

  • 引用计数法 (Reference Counting)
  • 根可达分析算法 (GCRooting Tracing)

引用计数法 (Reference Counting)

当对象引用消失,对象就称为垃圾

堆内存中主要存在三种引用关系:

  • 单一引用
  • 循环引用
  • 无引用
    在这里插入图片描述
    由上图可知,引用计数法,是无法发现 循环引用 这种情况的,易发生内存泄露问题。性能也是有问题的,要全部遍历一次,这是这种计数法的缺陷。

根可达分析算法 (GCRooting Tracing)

通过 GCRoots作为对象起点向下搜索,当一个对象到 GCRoots 没有任何引用链时此对象是垃圾
在这里插入图片描述

引用链 (ReferenceChain) : GCRoots 搜索走过的路径

垃圾对象死亡前至少经历两次标记:

  • 第一次:可达性分析,没有引用链对象会被第一次标记
  • 第二次:标记后的对象会经历筛选,如果筛选不通过,则会被第二次标记

对象引用类型

对象引用有哪些?

jdk 1.2之后,java对象的引用进行了扩充:强引用软引用、弱引用、虚引用

引用类型被垃圾回收时间用途生存时间
强引用从来不会对象的一般状态jvm停止时终止
软引用内存不足时对象缓存内存不足时终止
弱引用正常GC对象缓存GC后终止
虚引用正常GC类似事件回调机制GC后终止
无引用正常GC对象的一般状态GC后终止

强引用

代码中普遍的存在,只要强引用还在,就不会被GC。

Object obj = new Object();

软引用

非必须引用,内存溢出之前进行回收,如内存还不够,才会抛出异常。

package com.fun.info;

import java.lang.ref.SoftReference;

public class Reference {
    public static void main(String[] args) {
        Object obj = new Object();
        SoftReference<Object> sf = new SoftReference<>(obj);
        obj = null;
        // 有时候会返回 null
        Object o = sf.get();
        System.out.println("o==" + o);
    }
}

应用场景:软引用可用来实现内存敏感的高速缓存。
例如:

应用需要读取大量本地文件,如果每次读取都从硬盘读取会严重影响性能,如果一次性全部加载到内存,内存可能会溢出
可以使用软引用解决这个问题,使用一个HashMap来保存文件路径和文件对象管理的软引用之间的映射关系。
内存不足时,jvm会自动回收缓存文件对象的占用空间,有效避免 OOM 问题

HashMap<String, SoftReference<InputStream>> fileCache = new HashMap<>();

弱引用

非必须引用,只要有GC,就会被回收。

 Object o1 = new Object();
 WeakReference<Object> wf = new WeakReference<>(o1);
 o1 = null;
 // 有时候会返回 null
 Object o2 = wf.get();
 // 返回是否被垃圾回收器标记为即将回收的垃圾
 boolean enqueued = wf.isEnqueued();
 System.out.println("o1 = " + o2);
 System.out.println("enqueued =" + enqueued);
  • 虚引用是每次垃圾回收的时候都会被回收,通过虚引用的get方法永远获取到的数据为null,因此也被称为幽灵引用
  • 作用:跟踪对象被垃圾回收的状态,仅仅是提供一种确保对象被回收后,做某些事情的机制。类似监听机制。
  • ThreadLocalThreadLocalMap 就是用了弱引用。

清除垃圾

1.标记-清除算法 (Mark-Sweep)

  • 分为 标记清除 两个阶段:
    • 标记:标记出所有需要回收对象
    • 清除:统一回收掉所有对象
  • 缺点:
    • 执行效率不稳定
    • 空间碎片:会产生大量不连续内存碎片

2.复制算法 (Copying)

  • 内存分为两块,清除垃圾时,将存活对象复制到另一块
  • S0和S1区就是基于这个算法诞生的
  • Eden:S = 8:2
  • 不用担心S区不够,由Old做内存担保
  • 优缺点:
    • 优点:没有内存空间碎片化
    • 缺点:存在空间浪费

3.标记-整理算法 (Mark-Compact)

  • 标记:标记出所有需要回收对象
  • 清除:统一回收掉所有对象
  • 整理:将所有存活对象向一端移动
  • 优缺点:
    • 优点:空间没有浪费,没有内存碎片化问题
    • 缺点:性能较低

分代回收 (Generational Collection)

  • 新生代:选择 复制算法弱分代假说
  • 老年代:选择 标记-清除标记-整理,强分代假说

垃圾回收器

有 8 种不同的垃圾回收器,它们分别用于不同分代的垃圾回收

新生代 (复制算法) : Serial 、ParNew 、Parallel Scavenge
老年代 (标记-清除、标记-整理):SerialOld、Parallel Old、CMS
整堆:G1、ZGC

GC-串行收集器

Serial与SerialOld

配置参数:-XX:+UseSerialGC
特点:

  • Serial新生代收集器,单线程执行,使用复制算法
  • SerialOld老年代收集器,单线程执行,使用标记-整理算法
  • 进行垃圾收集时,必须暂停用户线程

SafePoint
垃圾回收时,是需要暂停用户线程的,如果产生垃圾的速度大于回收的速度,那永远回收不了。
SafePoint线程挂起的点主要有:

  • 循环的末尾
  • 方法返回前
  • 调用方法的call之后
  • 抛出异常的位置

并行收集器

Parallel Scavenge (Stop)

配置参数: -XX:+UseParallelGC
特点:简称 PS

  • 吞吐量优先收集器,垃圾收集需要暂停用户线程
  • 新生代使用并行回收器,采用复制算法
  • 老年代使用串行收集器,采用标记-整理算法

Parallel Old

配置参数: -XX:+UseParallelOldGC
特点:

  • PS收集器的老年代版本
  • 吞吐量优先收集器,垃圾收集需要暂停用户线程,对 CPU 敏感
  • 新生代使用复制算法
  • 老年代使用并行收集器,采用 标记-整理算法

ParNew

配置参数: -XX:+UseParNewGC
配置参数: -XX:ParallelGCThreads=n、垃圾收集线程数
特点:

  • 新生代并行ParNew,老年代串行SerialOld
  • Serial的多线程片
  • 单核CPU不建议使用

CMS

配置参数: -XX:+UseConcMarkSweepGC
特点:

  • 低延时,减少STW(Stop-The-World)对用户的影响
  • 并发收集,用户线程与收集线程一起执行,对CPU资源敏感
  • 不会等待堆填满再收集,到达阀值就开始收集
  • 采用 标记-清除算法 ,所以会产生内存碎片

实际上是精细了标记阶段的流程,降低 STW 来实现低延时

  • 初始标记阶段:会STW,标记出GCRoots可以关联到的对象 ,关联对象较少,所以很快
  • 并发标记阶段:不会STW,遍历GCRoots直接对象的引用链,耗时长
  • 重新标记阶段:会STW,修正并发标记期间的新对象记录
  • 并发清除阶段:不会STW,清除垃圾对象,释放内存空间

Garbage-First (G1)

G1是一款面向服务端应用的全功能垃圾收集器大内存 企业配置的主要是G1。
配置参数: -XX:+UseG1GC
特点

  • 吞吐量和低延时都行的整堆垃圾收集器
  • G1最大堆内存 32M2048 = 64GB,最小堆内存 1M2048=2GB,低于此值不建议使用
  • 全局使用标记-整理算法收集,局部采用复制算法收集
  • 可预测的停顿:能让使用者指定GC消耗时间(超过这个时间,则判断无回收价值,不会回收,即筛选回收),默认是200ms。

详细流程:

  • 初始标记:会STW,标记出GCRoots可以关联到的对象,耗时短
  • 并发标记:不会STW,遍历GCRoots直接对象的引用链,耗时长
  • 最终标记:会STW,修正并发标记期间,标记产生变动的那部分
  • 筛选回收:会STW,对各个Region的回收价值成本排序,根据用户期望GC停顿时间确定回收计划
G1内存划分

在这里插入图片描述
**取消新生代与老年代的物理划分:**采用若干个固定大小的Region

Region区类型(逻辑上):

  • Eden区
  • Survivor
  • Old
  • Humongous 当对象的容量超过了Region的50%,则被认为是巨型对象
# 使用G1垃圾收集器
-XX:+UseG1GC
# 设置期望达到的最大GC停顿时间指标(jvm会尽力实现,但不保证达到),默认值是 200 毫秒
-XX:MaxGCPauseMillis=
# 设置的 G1 区域的大小。值是 2 的幂,范围是 1MB 到 32MB 之间
# 目标是根据最小的 java 堆大小划分出约 2048 个区域
# 默认是堆内存的 1/2000
-XX:G1HeapRegionSize=n
# 设置并行垃圾回收线程数,一般将n的值设置为逻辑处理器的数量,建议最多为8.
-XX:ParallelGCThreads=n
# 设置并行标记的线程数。将n设置为ParallelGCThreads的1/4左右。
-XX:ConcGCThreads=n
# 设置触发标记周期的 java 堆占用率阀值。默认占用率是整个 java 堆的 45%
-XX:InitiatingHeapOccupancyPercent=n

ZGC

ZGC (Z Garbage Collector) 在 jdk11 中引入 的一种可扩展的低延迟垃圾收集器,在jdk15中发布稳定版本

配置参数: -XX:+UseZGC
特点:

  • <1ms最大暂停时间(jdk16是10ms,jdk16+是<1ms),不会随着堆内存增加而增加
  • 适合内存8MB,16TB
  • 并发,基于Region、压缩、NUMA感知、使用色彩指针、使用负载屏障
  • 垃圾收集算法:标记-整理算法
  • 主要目标:低延时

相关参数:

# 启用ZGC
-XX:+UseZGC
# 设置最大堆内存
-Xmx
# 打印 GC 日志
-Xlog:gc
# 打印 GC 详细日志
-Xlog:gc*

结束

至此,GC基本原理就结束了,如有疑问,欢迎评论区留言。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

力扣每日一题-K个元素的最大和-2023.11.15

力扣每日一题&#xff1a;K个元素的最大和 题目链接:2656.K个元素的最大和 题目描述 代码思路 题目看完直接笑嘻了&#xff0c;还有这么容易的题。由题可知&#xff0c;第一次要找出最大值m&#xff0c;那由于把m1放回去&#xff0c;那第二次找的就是m1&#xff0c;以此类推…

DGL如何表征一张图

有关于DGL中图的构建 DGL 将有向图表示为一个 DGL 图对象。图中的节点编号连续&#xff0c;从0开始。我们一般通过指定图中的节点数&#xff0c;以及源节点和目标节点的列表&#xff0c;来构建这么一个图。 下面的代码构造了一个图&#xff0c;这个图有五个叶子节点。中心节点…

python 多线程池 CPU拉满

前言&#xff1a; 关于多线程的博客先前的博客如下&#xff1a; python线程join方法_python 线程join-CSDN博客 【精选】Python GIL锁_python gil 锁-CSDN博客 python函数运行加速_python os.listdir速度慢_两只蜡笔的小新的博客-CSDN博客 只需下面的模版即可: from multi…

CNCC 2023收官,Milvus Cloud与行业大咖共话向量数据库系统

近期,CNCC 2023 在沈阳圆满结束,紧凑、前沿的 129 场技术论坛让人印象深刻。据悉,这 129 场技术论坛涵盖人工智能、安全、计算+、软件工程、教育、网络、芯片、云计算等 30 余个方向。Zilliz 受邀参与【智能时代的大数据系统】技术论坛。 智能时代的到来,无疑给社会经济和日…

前端 vue 面试题 (一)

文章目录 v-if,v-show差别v-for和v-if虚拟dom解决什么问题vue的data为什么返回函数不返回对象比较vue&#xff0c;reactvue双向绑定原理vue虚拟dom 的diff算法vue 虚拟dom的diff算法的时间复杂度vue2与vue3的区别vue数据缓存&#xff0c;避免重复计算单页应用怎么跨页面传参vue…

基于springboot实现学生选课平台管理系统项目【项目源码】

系统开发平台 在该地方废物回收机构管理系统中&#xff0c;Eclipse能给用户提供更多的方便&#xff0c;其特点一是方便学习&#xff0c;方便快捷&#xff1b;二是有非常大的信息储存量&#xff0c;主要功能是用在对数据库中查询和编程。其功能有比较灵活的数据应用&#xff0c…

队列与堆栈:原理、区别、算法效率和应用场景的探究

队列与堆栈&#xff1a;原理、区别、算法效率和应用场景的探究 前言原理与应用场景队列原理应用场景&#xff1a; 堆栈原理应用场景递归原理和堆栈在其中的作用递归原理堆栈作用 队列与堆栈区别队列堆栈算法效率 前言 本文主要讲解数据结构中队列和堆栈的原理、区别以及相关的…

解析数据洁净之道:BI中数据清理对见解的深远影响

本文由葡萄城技术团队发布。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 前言 随着数字化和信息化进程的不断发展&#xff0c;数据已经成为企业的一项不可或缺的重要资源。然而&#xff0c;这…

0基础学习VR全景平台篇第121篇:认识视频剪辑软件Premiere

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 大家好&#xff0c;这节课是带领大家认识认识我们的剪辑软件Premiere&#xff0c;一般简称是PR。 &#xff08;PR界面&#xff09; 我们首先打开PR&#xff0c;第一步就是要创建…

滚雪球学Java(64):LinkedHashSet原理及实现解析

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

【数据结构】堆(Heap):堆的实现、堆排序、TOP-K问题

目录 堆的概念及结构 ​编辑 堆的实现 实现堆的接口 堆的初始化 堆的打印 堆的销毁 获取最顶的根数据 交换 堆的插入&#xff08;插入最后&#xff09; 向上调整&#xff08;这次用的是小堆&#xff09; 堆的删除&#xff08;删除根&#xff09; 向下调整&#xff08;这次用的…

dgl 的cuda 版本 环境配置(dgl cuda 版本库无法使用问题解决)

1. 如果你同时有dgl dglcu-XX.XX 那么&#xff0c;应该只会运行dgl &#xff08;DGL的CPU版本&#xff09;&#xff0c;因此&#xff0c;你需要把dgl(CPU)版本给卸载了 但是我只卸载CPU版本还不够&#xff0c;我GPU 版本的dglcu依旧不好使&#xff0c;因此吧GPU版本的也得卸载…

Python武器库开发-flask篇之路由和视图函数(二十二)

flask篇之路由和视图函数(二十二) 通过创建路由并关联函数&#xff0c;实现一个基本的网页&#xff1a; #!/usr/bin/env python3 from flask import Flask# 用当前脚本名称实例化Flask对象&#xff0c;方便flask从该脚本文件中获取需要的内容 app Flask(__name__)#程序实例需…

2.5 Windows驱动开发:DRIVER_OBJECT对象结构

在Windows内核中&#xff0c;每个设备驱动程序都需要一个DRIVER_OBJECT对象&#xff0c;该对象由系统创建并传递给驱动程序的DriverEntry函数。驱动程序使用此对象来注册与设备对象和其他系统对象的交互&#xff0c;并在操作系统需要与驱动程序进行交互时使用此对象。DRIVER_OB…

云服务器如何选?腾讯云2核2G3M云服务器88元一年!

作为一名程序员&#xff0c;在选择云服务器时&#xff0c;我们需要关注几个要点&#xff1a;网络稳定性、价格以及云服务商的规模。这些要素将直接影响到我们的使用体验和成本效益。接下来&#xff0c;我将为大家推荐一款性价比较高的轻应用云服务器。 腾讯云双11活动 腾讯云…

vue-组件通信(动态组件)

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Vue篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue-组件通信|动态组件 目录 组件通信 1.父传子 2.子传父 3.ref 4.兄弟组件 5.跨层级 provid…

Git用pull命令后再直接push有问题

在gitlab新建一个项目&#xff0c;然后拉取到本地&#xff0c;用&#xff1a; git init git pull <远程主机名> 然后就是在本地工作区增加所有文件及文件夹。再添加、提交&#xff0c;都没问题&#xff1a; 但是&#xff0c;git push出问题&#xff1a; 说明本地仓库和…

手把手带你学习 JavaScript 的 ES6 ~ ESn

文章目录 一、引言二、了解 ES6~ESn 的新特性三、掌握 ES6~ESn 的用法和实现原理四、深入挖掘和拓展《深入理解现代JavaScript》编辑推荐内容简介作者简介精彩书评目录 一、引言 JavaScript 是一种广泛使用的网络编程语言&#xff0c;它在前端开发中扮演着重要角色。随着时间的…

3类主流的车道检测AI模型

2014年的一天&#xff0c;我舒舒服服地躺在沙发上&#xff0c;看着我和加拿大朋友租的豪华滑雪别墅的篝火营地&#xff0c;突然&#xff0c;一个东西出现在我的视野里&#xff1a; “着火了&#xff01;着火了&#xff01;着火了&#xff01;” 我大喊。 几秒钟之内&#xff…

基于springboot实现学生选课平台管理系统项目【项目源码】计算机毕业设计

基于springboot实现学生选课平台管理系统演示 系统开发平台 在该地方废物回收机构管理系统中&#xff0c;Eclipse能给用户提供更多的方便&#xff0c;其特点一是方便学习&#xff0c;方便快捷&#xff1b;二是有非常大的信息储存量&#xff0c;主要功能是用在对数据库中查询和…