当前位置: 首页 > news >正文

05、GC基础知识

JVM程序在跑起来之后,在数据的交互过程中,就会有一些数据是过期不用的,这些数据可以看做是垃圾,JVM中,这些垃圾是不用开发者管的,它自己会有一套垃圾回收系统自动回收这些内存垃圾,以备后面继续使用。这就是JVM的GC系统。GC这块知识很多,这篇文章主要是了解下它的基本知识点
1、如何定位垃圾
2、GC的回收算法
3、GC的内存分代模型

1、如何定位垃圾

  • 引用计数法:它的核心思想是,没有引用指向的内存区域是垃圾区域,GC可以回收这个区域。具体的做法是,每当有引用指向这个对象,它对应的计数就+1,当有引用取消了对它的指向就-1,如果计数为0的时候,它就会被GC自动回收。
    • 它的问题:引用计数法如果碰到循环引用的垃圾,就会失效。比如a引用b,b也引用a,但是他们整体的引用在程序中已经释放掉了,但是由于它们互相引用,引用计数永远不可能为0,所有它们永远不会被回收。
    • 它的解决方案是如下的“根可达算法”来解决
  • 根可达算法:它的核心思想是,如果一个对象没有根对象直接或间接的指向它,那它就是垃圾。具体的是要弄清楚哪些是属于根对象
    根对象
    • 根对象:
      • JVM Stacks里的对象(线程栈变量)
      • Native Method Stack(本地方法栈的对象)
      • Run-time Constant Pool(常量池里的对象)
      • Static Refercens In Method Area(方法区的静态对象)

      程序跑起来也就是main函数跑起来之后,它里面需要用到的对象都算是根对象,如线程栈变量和本地方法栈变量,然后就是用Static申请的对象,如果是字符串类型那就是常量池数据,如果是静态的引用那就是方法区的对象,这些算是根对象。它们直接或是间接引用的对象都不能算是垃圾。

2、GC回收算法

  • 标记清楚算法
    • 具体实现:第一阶段根据GCRoot规则把存活对象进行标记,第二阶段会清楚掉没有标记的对象
    • 特点:根据它的工作特点可以发现,清除之后留下来的内存不连续,会产生内存碎片。需要经过两次扫描,效率低
    • 使用场景:适用于对象存活时间长的情况,不如old区
  • 拷贝算法
    • 具体实现:首先把内存区域分为两部分A,B区域,一部分空置着(比如B区),等另外一部分(A区)满了之后,直接把A区存活对象复制到B区,然后把A区数据全部清除
    • 特点:内存位置连续,无碎片化,扫描一次即可,但是需要移动和复制内存对象,且浪费空间,有效利用率只有50%
    • 使用场景:适用于对象存活时间短的场景,比如年轻代的from区和to区
  • 标记压缩算法
  • 具体实现:它跟标记清楚算法类似,都需要经过两次扫描,不一样的是,第二阶段并不是删除未标记对象,而是把标记对象压缩到内存的一端,之后清理掉其他的空间
  • 特点:位置连续,没有碎片,内存的利用率也很高,但也是需要两次扫描且需要把对象移动到头部,效率偏低
  • 使用场景:适用于对象存活时间较长的情况,比如old区

3、GC内存分代模型

3.1、常见的GC,以及他们之间的组合

GC类型

Serial系列的GC是最早版本的,它都是单线程串行回收垃圾,一般针对几十兆内存的机器

  • Serial:底层用的是复制算法+单线程,用于年轻代回收
  • Serial Old:底层用的是标记压缩算法+但线程,用于老年代回收

PS+PO算法是JDK1.8版本以及之前版本默认的GC,他们都是并行回收的,一般能回收几个G的内存数据

  • Parallel Scavenge:拷贝算法+并行,用于年轻代
  • Parallel Old:标记清除算法+并行,用于老年代

PN+CMS算法是较新的一种组合,它们是期望用于更大内存的回收,其中PN算法是配合CMS对年轻代回收的一种算法

  • ParNew:拷贝算法+并行计算
  • CMS:三色标记算法+并行计算
  • G1,ZGC,Shenandoah:这些都是新一代的GC,后面会具体篇幅专门介绍。

3.2、GC的分代模型

Serial系列,Parallel Scavenge,Parallel Old,ParNew,CMS,这些都是逻辑和物理上都是进行分代的,G1是逻辑上分代,但是物理上是不分代的,之后的GC如ZGC,Shenandoah他们逻辑和物理上都不分代。如果分代的话,一般分为年轻代和老年代,他们默认的占比是New:Old=1:2

  • 年轻代:Eden+2个Survival区(from+to区),它们内存占比默认是8:1:1,其中一个区域满了就会触发YGC。from区和to区一般只有一个区域是在使用的
  • 老年代:垃圾相对于较少,如果满了之后会触发FullGC
3.2.1、对象在各个分代区域的流转规则
  • Young区的数据流转

在Young区,如果Eden区满了,就会触发YGC,就会把Eden区存活的对象复制到from区,然后清除掉Eden,如果from区满了,会把数据复制到to区,清除掉from,Young区的流转大致如上所述。

  • Old区的数据流转

Old 区的数据都是从Young流转过来的,具体的流转条件如下所述

  • 大对象直接进入Old区(通过GC参数-XX:+MaxTenuringThreshold 来设定)
  • 动态年龄:如年龄1的占33%,年龄2的占33%,年龄3的占34%,年龄2+年龄3>50%,所以年龄2,3的对象同时晋升到old区
  • 分配担保:YGC期间Survivor区空间不够时,担保的空间直接进入Old区
  • age年龄到了15岁时会进入Old区

http://www.mrgr.cn/news/80296.html

相关文章:

  • 微信小程序中 crypto-js 加解密全攻略
  • 利用git上传项目到GitHub
  • 事务进阶和上传文件
  • Docker的镜像
  • Vue项目打包部署到服务器
  • AI知识-多模态(Multimodal)
  • 【从零开始入门unity游戏开发之——C#篇11】一个标准 C# 程序介绍、新的值类型——枚举
  • spring实例化对象的几种方式(使用XML配置文件)
  • Golang囊地鼠gopher
  • 【教学类-83-01】20241215立体书三角嘴1.0——小鸡(正菱形嘴)
  • 修炼之道 --- 其二
  • LRM-典型 Transformer 在视觉领域的应用,单个图像生成3D图像
  • 将带注释的Word文档改造成点击注释引用即可弹窗显示注释的HTML文档
  • 学习Guava库 学习实用示例 实例 核心提纲
  • gorm源码解析(一):ORM概览
  • tryhackme——Defensive Security Intro(防御安全简介)
  • opencv小练习(未完成版)
  • google 的guava 学习 基本工具类
  • WPF 相比 winform 的优势
  • 一、windows上配置ninja环境
  • Leetcode 面试150题 399.除法求值
  • Windows 系统下 Python 环境安装
  • Ansible自动化运维(五) 运维实战
  • 域名信息收集(小迪网络安全笔记~
  • 2024.12.15CISCN长城杯铁人三项赛
  • Jinja2模板、Roles角色详解