JVM的垃圾回收算法有哪些?从可达性分析算法开始,深入解读三大核心垃圾回收算法

导航:

【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/黑马旅游/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码-CSDN博客 

目录

一、概念准备

1.1 GC Roots

1.2 可达性分析算法

1.3 非可达对象被回收过程中的两次标记

1.4 finalize()方法

二、垃圾回收算法

2.1 标记清除算法(Mark-Sweep)

2.2 标记复制算法(Copying) 

2.3 标记整理算法(Mark-Compact) 

2.4 小结:三种垃圾回收对比

三、分代收集理论


 

一、概念准备

1.1 GC Roots

GC Roots:即GC根节点集合,是一组必须活跃的引用,这些对象一定是存活的,不需要被垃圾回收器回收。GC即Garbage Collection,译为垃圾回收。

可作为GC Roots的对象:

  • 本地方法栈中引用的对象:即由本地方法中的局部变量所引用的对象。本地方法栈用于管理本地方法的调用,这些本地方法底层是用C语言写的,被编译为基于本机硬件和操作系统的程序,它们引用的对象不会被回收,所以是GC Root。
  • 虚拟机栈中引用的对象:虚拟机栈又称Java方法栈,即由 Java 方法中的局部变量所引用的对象。虚拟机栈中的局部变量、参数以及返回值等都是直接引用对象的,他们是明确的、在程序运行期间被访问到的对象,所以它们也是GC Root。
  • 方法区中常量、静态变量引用的对象:常量不可变、静态变量先于对象产生,被所有该类的对象共享,所以它们都可认为是GC Root。final修饰的类不可被继承、方法不可被重写、变量不可变。静态变量是类变量,优先于对象产生。常量、静态变量都存放在JVM方法区的类常量池中,类常量池在类加载阶段从Java字节码文件中解析。
  • 所有被同步锁持有的对象:在 Java 虚拟机中,线程持有同步锁时,该对象就是被线程所引用的,即使在程序的其他部分没有对该对象进行引用,它也不会被回收。
  • 所有线程对象:线程对象是程序执行的基本单位之一,他们被创建后,会一直存在直到它们被显式地销毁或者程序运行结束。
  • 所有跨代引用对象:年轻代和老年代之间相互引用的对象成为跨带引用对象。
  • JVM内部的引用:如基本数据类型对应的Class对象,常驻的异常对象(如空指针异常、参数不合法异常,他们在JVM启动过程中就被加载,因为它们太常用了),以及应用程序类类加载器; 

回顾JVM内存模型:

对JVM内存模型(方法区、堆、栈等元素) 不熟悉,可以参考下文:

什么是JVM的内存模型?详细阐述Java中局部变量、常量、类名等信息在JVM中的存储位置-CSDN博客

 

1.2 可达性分析算法

以所有GC Roots为起始点,根据引用关系向下搜索,将所有与GC Roots直接或间接有引用关系的对象在对象头的Mark Word里标记为可达对象,即不需要回收的有引用关系对象。搜索过程所走过的路径称为“引用链” 。

例如下面对象1,2,3,4都在GC Roots的引用链上,所以它们都是可达对象,不会被回收。而对象5,6,7因为没有跟任何一个GC Root直接或间接产生调用关系,所以它们是非可达对象,需要被回收。

 

1.3 非可达对象被回收过程中的两次标记

非可达对象被回收需要两次标记:

  1. 第一次标记后筛选非可达对象:
    1. 非可达对象第一次被可达性分析算法标记后,会进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法,也就是是否有机会自救。
    2. 假如对象没有覆盖或者已被JVM调用过finalize()方法,也就是说不想自救或已自救过,那么此对象需要被回收;
    3. 假如对象覆盖并没被JVM调用过finalize()方法,该对象将会被放置在一个名为F-Queue的队列之中,并在稍后由一条由虚拟机自动建立的、低调度优先级的Finalizer线程去执行它们的finalize()方法,完成自救后它们就不会被回收。
  2. 第二次标记F-Queue里的未自救对象:
    1. 稍后,收集器将对F-Queue中的对象进行第二次小规模的标记。
    2. 如果对象要在finalize()中成功拯救自己——只要重新与引用链上的任何一个对象建立关联即可,譬如把自己(this)赋值给某个引用类型的类变量或者对象的成员变量,那在第二次标记时它将被移出“即将回收”的F-Queue。如果对象这时候还没有逃脱,那它就真的要被回收了。

1.4 finalize()方法

Java中,任何对象都直接或间接是Object类的子类,finalize()是Object类中的一个方法,所以可以说,Java中任何类都有一个finalize()方法。finalize()方法是对象逃脱死亡命运的最后一次机会。

需要注意的是,任何一个对象的finalize()方法都只会被系统自动调用一次,如果对象面临下一次回收,它的finalize()方法不会被再次执行。

另外,finalize()方法的运行代价高昂,不确定性大,无法保证各个对象的调用顺序,如今已被官方明确声明为不推荐使用的语法。

finalize()方法所在位置:

二、垃圾回收算法

2.1 标记清除算法(Mark-Sweep)

步骤: 

  1. 标记、清除:当堆中有效内存空间被耗尽时,会STW(stop the world,暂停其他所有工作线程),然后先标记,再清除。
  2. 标记:可达性分析法,从GC Roots开始遍历,找到可达对象,并在对象头中进行标记。
  3. 清除:堆内存内从头到尾进行线性遍历,“清除”非可达对象。注意清除并不是真的置空,垃圾还在原来的位置。实际是把垃圾对象的地址维护在空闲列表,对象实例化的申请内存阶段会通过空闲列表找到合适大小的空闲内存分配给新对象。

 

对象头: Hotspot 虚拟机中每个对象都有一个对象头(Object Header),包含Mark Word(标记字段) 和 Class Pointer(类型指针)。

  • Mark Word(标记字段):存储哈希码、GC分代年龄、锁信息、GC标记(标志位,标记可达对象或垃圾对象)等。锁信息包括:
    • 锁标志位:64位的二进制数,通过末尾能判断锁状态。01未锁定、01可偏向、00轻量级锁、10重量级锁、11垃圾回收标记
    • 偏向锁线程ID、时间戳等;
    • 轻量级锁的指针:指向锁记录的指针
    • 重量级锁的指针:指向Monitor锁的指针
  • 类型指针:指向它的类元数据的指针,用于找到对象所在的类。  

 

优缺点和使用场景:

  • 优点:简单
  • 缺点:
    • 效率不高:需要可达性遍历和线性遍历,效率差。
    • STW导致用户体验差:GC时需要暂停其他所有工作线程,用户体验差。
    • 有内存碎片,要维护空闲列表:回收垃圾对象后没有整理,导致堆中出现一块块不连续的内存碎片。
  • 适用场景:适合小型应用程序,内存空间不大的情况。应用程序越大越不适用这种回收算法。

 

2.2 标记复制算法(Copying) 

在开始阶段,将内存空间分为两块,每次只使用一块。 

步骤:  

  • 标记:在进行垃圾回收时,先可达性分析法标记可达对象。
  • 复制:然后将可达对象复制到没有被使用的那个内存块中;
  • 清除:最后清除旧内存块中的所有对象。、
  • 后续再按同样的流程来回复制和清除。

 

优缺点和使用场景:

  • 优点:
    • 垃圾多时效率高:只需可达性遍历,效率很高。
    • 无内存碎片:因为有移动操作,所以内存规整。
  • 缺点:
    • 内存利用率低,浪费内存:始终有一半以上的空闲内存。
    • 需要调整引用地址:可达对象移动后,内存地址发生了变化,需要调整所有引用,指向移动后的地址。
    • 垃圾少时效率相对差,但还是比其他算法强:如果可达对象比较多,垃圾对象比较少,那么复制算法的效率就会比较低。只为了一点垃圾而移动所有对象未免有些小题大做。所以垃圾对象多的情况下,复制算法比较适合。
  • 适用场景:
    • 适合垃圾对象多,可达对象少的情况,这样复制耗时短。
    • 非常适合新生代的垃圾回收,因为新生代要频繁地把可达对象从伊甸园区移动到幸存区,而且是新生代满了适合再Minor GC,垃圾对象占比高,所以回收性价比非常高,一次通常可以回收70-90%的内存空间,现在的商业虚拟机都是用这种GC算法回收新生代。

2.3 标记整理算法(Mark-Compact) 

步骤:   

  • 标记:首先可达性分析法标记可达对象;
  • 整理:然后将可达对象按顺序整理到内存的一端;
  • 清除:最后清理边界外的垃圾对象。

标记整理算法相当于内存碎片优化版的标记清楚算法,不用维护空闲列表。

 

优缺点和使用场景:

  • 优点:
    • 无内存碎片:内存规整。
    • 内存利用率最高:内存既规整又不用浪费一般空间。
  • 缺点:
    • 效率最低:效率比其他两种算法都低
    • 需要调整引用地址:可达对象移动后,内存地址发生了变化,需要调整所有引用,指向移动后的地址。
    • STW导致用户体验差:移动时需要暂停其他所有工作线程,用户体验差。

2.4 小结:三种垃圾回收对比

标记清除算法标记复制算法标记整理算法
速度中等最快最慢
时间开销mark阶段与存活对象的数量成正比,sweep阶段与整堆大小成正比与存活对象大小成正比mark阶段与存活对象的数量成正比,compact阶段与整堆大小成正比,与存活对象的大小成正比
空间开销少(但会堆积碎片)通常需要存活对象的2倍大小(不堆积碎片)少(不堆积碎片)
移动对象

 

三、分代收集理论

垃圾回收器都不会只选择一种算法,JVM根据对象存活周期的不同,将内存划分为几块。一般是把堆分为新生代和老年代,根据年代的特点来选择最佳的收集算法。

分代收集算法:将堆分为新生代、老年代不同生命周期的对象放在不同的代,采用不同的收集算法,以提高回收效率。 

HotSpot 中大部分垃圾回收器都采用分代回收的思想,即新生代用一种垃圾回收算法,老年代用一种垃圾回收算法。

以JDK8为例,JDK8默认回收器是Parallel+Parallel Old,新生代用Parallel回收器,老年代用Parallel Old回收器。

回收过程:

  1.  首先,任何新对象都分配到 eden 空间。两个幸存者空间开始时都是空的。
  2. 当 eden 空间填满时,将触发一个Minor GC(年轻代的垃圾回收,也称为Young GC),删除所有未引用的对象,大对象(需要大量连续内存空间的Java对象,如那种很长的字符串)直接进入老年代。
  3. 所有被引用的对象作为存活对象,将移动到第一个幸存者空间S0,并标记年龄为1,即经历过一次Minor GC。之后每经过一次Minor GC,年龄+1。GC分代年龄存储在对象头的Mark Word里。
  4. 当 eden 空间再次被填满时,会执行第二次Minor GC,将Eden和S0区中所有垃圾对象清除,并将存活对象复制到S1并年龄加1,此时S0变为空。
  5. 如此反复在S0和S1之间切换几次之后,还存活的年龄等于15的对象(JDK8默认15,JDK9默认7,-XX:InitialTenuringThreshold=7)在下一次Minor GC时将放到老年代中。 
  6. 当老年代满了时会触发Major GC(也称为Full GC),Major GC 清理整个堆 – 包括年轻代和老年代。

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

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

相关文章

vue从入门到精通(一):初始Vue

一,Vue是什么 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代…

质量保障之精准测试!

一、背景与概念 随着软件测试行业的长足发展,测试理念、技术都在发生着日新月异的变化。因此一套完整的自动化测试用例对于每个软件公司都是不可或缺的,然而虽然有如此规模宏大的自动化案例集资源投入,同时也有大量人力的投入,但…

虚拟仿真云平台在教育应用中的优势和意义

虚拟仿真云实验教学平台作为一种新型的教学方法,近年来在高校教育中得到了十分广泛的应用。它通过模拟真实的实验场景和实验操作,让学生在计算机上进行实验操作和数据处理,为学生提供了更加便捷、可靠、有效的实验学习环境。本文,…

Python如何绘制直流电机开闭环特性曲线?matplotlib

import matplotlib.pyplot as plt from pylab import mplmpl.rcParams[font.sans-serif] [FangSong] # 指定默认字体 mpl.rcParams[axes.unicode_minus] False # 解决保存图像是负号-显示为方块的问题# 数据集1 n1 [1206, 1174, 1141, 1116, 1037, 986] Id1 [0.505, 0.55…

【多模态】30、GPT4V_OCR | GPT4V 在 OCR 数据集上效果测评

文章目录 一、背景二、测评2.1 场景文本识别2.2 手写文本识别2.3 手写数学公式识别2.4 图表结构识别(不考虑单元格中的文本内容)2.5 从内容丰富的文档中抽取信息 三、讨论 论文:EXPLORING OCR CAPABILITIES OF GPT-4V(ISION) : A QUANTITATIV…

centos7.6安装mysql

博客主页:花果山~程序猿-CSDN博客 文章分栏:MySQL之旅_花果山~程序猿的博客-CSDN博客 关注我一起学习,一起进步,一起探索编程的无限可能吧!让我们一起努力,一起成长! 目录 1.在网页中寻找mysql…

【QT】QT环境搭建

本专栏内容为:QT学习专栏 通过本专栏的深入学习,你可以了解并掌握QT。 💓博主csdn个人主页:小小unicorn ⏩专栏分类:QT 🚚代码仓库:小小unicorn的代码仓库🚚 🌹&#x1f…

WordPress 管理员密码重置方法汇总

最近明月碰到一个 WordPress 站长求助咨询,说是自己 WordPress 站点的管理员密码被恶意篡改了,对 WordPress 了解的都知道这一般都是恶意代码造成的,问题大多出在使用了所谓的破解版、去授权版的插件或者主题被植入了恶意代码、后门木马。明月…

洗地机哪个牌子好性价比高又实惠?高性价比洗地机推荐【避坑指南】

洗地机是一种智能清洁家具,具有强大的清洁能力,可快速有效地清洁各种地面污渍,操作简便,省时省力。其一键操作功能使其易于上手,无需频繁清洗拖布和更换水,大大提高了清洁效率。部分高端洗地机还具备智能感…

全国防灾减灾日主题活动投稿我可算找对了投稿方法

作为一名社区公众人员,我深知对外信息宣传的重要性。特别是在全国防灾减灾日这样的特殊时刻,我们不仅要向居民普及防灾减灾知识,还要通过媒体将社区的活动和成果展示给更多人。然而,在投稿的过程中,我最初却遭遇了诸多挑战。 起初,我采用传统的邮箱投稿方式,将精心撰写的稿件发…

小程序常用组件

小程序常用组件 1.组件的定义2.常用组件3.引入外部字体图标库4.组件样式5.示例代码 1.组件的定义 组件就是指微信定义的具有特殊功能的标签&#xff0c;在wxml中只能使用微信定义的标签。 2.常用组件 <view>&#xff1a;用于页面布局的块级组件&#xff0c;类似于html中的…

jmeter分布式集群压测

目的&#xff1a;通过多台机器同时运行 性能压测 脚本&#xff0c;模拟更好的并发压力 简单点&#xff1a;就是一个人&#xff08;控制机controler/调度机 master&#xff09;做一个项目的时候&#xff0c;压力有点大&#xff0c;会导致结果不理想&#xff0c;这时候找几个人&a…

OS复习笔记ch5-4-2

引言 承接上文我们介绍了信号量机制和应用信号量机制实现的进程同步和互斥&#xff0c;这一节我们将围绕一些经典问题对信号量机制展开更深入地探讨。 读者/写者问题 读者/写者问题与我们之前遇到的问题类型不同&#xff0c;它描述的是&#xff1a; 有读者和写者两组进程&am…

ohmyzsh的安装过程中失败拒绝连接问题的解决

1.打开官网Oh My Zsh - a delightful & open source framework for Zsh 在官网能看到下面的界面 有这两种自动安装的方式 个人本次选择的是: wget https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O - 1.打开终端输入安装的指令 sh -c "$(wget…

软件需求工程习题

1.&#xff08;面谈&#xff09;是需求获取活动中发生的需求工程师和用户间面对面的会见。 2.使用原型法进行需求获取&#xff0c;&#xff08;演化式&#xff09;原型必须具有健壮性&#xff0c;代码质量要从一开始就能达到最终系统的要求 3.利用面谈进行需求获取时&#xf…

K邻近算法

简介 介绍了非常简单的算法&#xff1a;K邻近算法&#xff0c;即KNN。 基本介绍 K-近邻算法&#xff08;K-Nearest Neighbors&#xff0c;简称KNN&#xff09;是一种基本且广泛应用的监督学习算法&#xff0c;主要用于分类和回归任务。 工作原理非常简答直观&#xff1a;所谓…

爆款小红书免费流量体系课程(两周变现),小红书电商教程

课程下载&#xff1a;小红书电商教程-课程网盘链接提取码下载.txt资源-CSDN文库 更多资源下载&#xff1a;关注我。 课程内容&#xff1a; 10-爆款标题(三段式取标题).mp3 11-爆款封面怎么作图.mp3 12-爆款内容的模板(三段式模板).mp3 13-小红书流量推荐背后的秘密(四大流…

数据结构与算法-排序算法1-冒泡排序

本文先介绍排序算法&#xff0c;然后具体写冒泡排序。 目录 1.排序算法简介 2.常见的排序算法分类如下图&#xff1a; 3.冒泡排序&#xff1a; 1.介绍&#xff1a; 2.动态图解 3.举例 4.小结冒泡排序规则 5.冒泡排序代码 6.优化 7.优化后时间 代码&#xff1a; 运…

讯方·智汇云校4月HCIE通过28人!证书量总计123!

智汇云校捷报 —4月华为认证证书量123本— 智汇云校4月IE捷报来了 讯方技术2024年PMP第一期3月考期顺利结班&#xff0c;考试全员通过~ 2024年4月&#xff0c;云校HCIA、HCIP、HCIE共通过123人&#xff01; 62人通过HCIA 33人通过HCIP 28人通过HCIE 祝贺以下学员通过HC…

simulink-仿真以及PID参数整定/PID tuner 的使用流程

控制器搭建与参数整定 搭建一个前馈PID控制器控制系统PID tuner使用 一个懂点控制但不多的小白&#xff0c;因为需要利用simulink仿真&#xff0c;所以不得不学习一些仿真的知识&#xff0c;这篇文章适合和我一样的新手入门&#xff0c;有理解错误的地方希望大手们能够指出来共…