Java垃圾回收算法

垃圾回收之标记算法

1、引用计数法

  • 通过判断对象的引用数量来决定对象是否被回收
  • 每个对象实例都有一个引用计数器,被引用则+1,完成引用则-1

  优点: 执行效率高,程序执行受影响小

  缺点: 无法检测出循环引用的情况,导致内存泄漏

 应用较少

2、可达性分析算法

   通过判断对象的引用链是否可达来决定对象是否可以被回收。

   将程序中所有的引用链视为一张图,从一系列的GC Root 出发,无法到达的节点则标记为可回收。

 可以作为GC Root的对象:

  • 虚拟机栈中引用的对象(栈帧中的局部变量表)
  • 方法区中的常量引用的对象
  • 方法区中的类静态属性引用的对象
  • 本地方法栈中JNI的引用对象
  • 活跃线程的引用对象

垃圾收集(Garbage Collection, GC)是一种自动化的内存管理机制,它负责回收不再使用的对象所占用的内存。以下是几种常见的垃圾收集算法:

1、标记-清除算法
标记-清除(Mark-Sweep)算法是最基础的收集算法,它分为标记和清除两个阶段。
首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象,它的标记过程其实就是垃圾判定算法中介绍的过程。
该算法有两个缺点:

效率问题:标记和清除两个过程的效率都不高
空间碎片:标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
执行过程:


 

2、复制算法
复制(Copying)算法解决了效率低的问题。它将可用内存容量划分为大小相等的两块,每次只使用其中的一块。当这一块内存用完了,就将还存活的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,简单高效。

优点:解决碎片化问题
缺点:可用内存缩小为原来的一半,代价有点儿高。

使用场景:适用于对象存活率低的场景,例如新生代

执行过程:

现在的商业虚拟机都采用这种收集算法来回收新生代。
通常将内存分为一块较大的Eden区和两块较小的Survivor区,每次使用Eden和其中一块Survivor。当回收时,将Eden和Survivor中还存活的对象一次性地复制到另外一块Survivor区,最后清理掉Eden和刚用过的Survivor区。据研究表明,新生代中的对象98%是朝生夕死的。
HotSpot默认Eden和Survivor的大小比例是8:1:1,也就是每次新生代中可用内存空间为整个新生代容量的90%。
当然,并98%只是一般场景下的统计数据,实际上没办法保证每次回收都只有不多于10%的对象存活。当Survivor空间不够用时,需要依赖其他内存进行分配担保(Handle Promotion)。

3、标记-整理算法
复制算法在对象存活率较高时需要进行较多的复制操作,效率会降低很多。更关键的是需要有额外的空间进行分配担保,以应对内存中所有对象100%存活的极端情况,所以老年代一般不能直接选择这种算法。
标记-压缩(Mark-Compact)算法,也叫标记-整理算法。标记过程仍然与标记-清除算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。

特点:

  • 避免了内存的不连续性
  • 不用设置两块内存互换
  • 适用于存活率高的场景,例如老年代

执行过程:


 

4、分代收集算法(主流)
现在虚拟机的垃圾收集都采用分代收集(Generational Collection)算法。这种算法根据对象存活周期的不同将内存划分为几块。
一般把Java堆分为新生代和老年代,然后根据各个年代的特点采用最适当的收集算法。

新生代:每次收集时都有大批对象死去,只有少量存活,选用复制算法,只需要复制出少量存活对象就可以快速完成收集。
老年代:对象存活率高、没有额外空间对它进行分配担保,一般使用标记-清理或标记-压缩算法。

GC的分类:

1、Minor GC:年轻代的垃圾收集,采用复制算法。执行较为频繁,尽可能快速地回收生命周期短的对象。

2、Full GC/ Major GC: 老年代回收,一般情况下同时也会触发Minor GC

常见的垃圾回收器

1、年轻代垃圾回收器

  Serial收集器(-XX:UseSerialGC, 复制算法)

  • 单线程收集,进行垃圾收集时,必须暂停所有工作线程
  • 简单高效,Client模式下默认的年轻代收集器

  ParNew收集器(-XX:UseParNewGC, 复制算法)

  • 多线程收集,其余的行为特点和Serial收集器一样
  • 单核执行效率不如Serial,在多核下执行才有优势 

  Parallel Scavenge收集器 (-XX:UseParallelGC, 复制算法)

  • 比起关注用户线程停顿时间,更关注系统的吞吐量(这里吞吐量是指  运行用户代码时间/(运行用户代码时间+垃圾收集时间))
  • 在多核下执行有优势,Server模式下默认的年轻代收集器

2.老年代垃圾回收器

  Serial Old收集器(-XX:UseSerialOldGC, 标记-整理算法)

  • 单线程收集,进行垃圾收集时,必须暂停所有工作线程
  • 简单高效,Client模式下默认的老年代收集器

  Parallel Old收集器(-XX:UseParallelOldGC,标记-整理算法)

  • 多线程, 吞吐量优先

  CMS收集器(-XX:UseConcMarkSweepGC, 标记清除算法)

  CMS全称 Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器,以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器,对于要求服务器响应速度的应用上,这种垃圾回收器非常适合。

  回收流程:

  • 初始标记:在这个阶段,需要虚拟机停顿正在执行的任务,官方的叫法STW(Stop The Word)。这个过程从垃圾回收的"根对象"开始,只扫描到能够和"根对象"直接关联的对象,并作标记。所以这个过程虽然暂停了整个JVM,但是很快就完成了。
  • 并发标记:这个阶段紧随初始标记阶段,在初始标记的基础上继续向下追溯标记。并发标记阶段,应用程序的线程和并发标记的线程并发执行,所以用户不会感受到停顿。
  • 并发预清理:并发预清理阶段仍然是并发的。在这个阶段,虚拟机查找在执行并发标记阶段新进入老年代的对象(可能会有一些对象从新生代晋升到老年代, 或者有一些对象被分配到老年代)。通过重新扫描,减少下一个阶段"重新标记"的工作,因为下一个阶段会Stop The World。
  • 重新标记:这个阶段会stop the world,收集器线程扫描在CMS堆中剩余的对象。扫描从"根对象"开始向下追溯,并处理对象关联。
  • 并发清理:清理垃圾对象,收集器线程和应用程序线程并发执行
  • 并发重置:这个阶段,重置CMS收集器的数据结构,等待下一次垃圾回收。

  CMS不会整理、压缩堆空间,这样就带来一个问题:经过CMS收集的堆会产生空间碎片,CMS不对堆空间整理压缩节约了垃圾回收的停顿时间,但也带来的堆空间的浪费。为了解决堆空间浪费问题,CMS回收器不再采用简单的指针指向一块可用堆空 间来为下次对象分配使用。;而是把一些未分配的空间汇总成一个列表,当JVM分配对象空间的时候,会搜索这个列表找到足够大的空间来hold住这个对象。

3. G1 收集器(-XX: UseG1GC, 复制+ 标记整理算法,独立的垃圾回收器包含新生代、老年代)

  G1(Garbage-First)是一款面向服务端应用的垃圾收集器,主要针对配备多核CPU及大容量内存的机器,以极高概率满足GC停顿时间的同时,还兼具高吞吐量的性能特征。JDK 9以后的默认垃圾收集器,取代了CMS 回收器。

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

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

相关文章

文献阅读 | Nature Communications:使用自适应图注意自动编码器从空间解析的转录组学中解读空间域

文献介绍 文献题目: 使用自适应图注意自动编码器从空间解析的转录组学中解读空间域 研究团队: 张世华(中国科学院数学与系统科学研究院) 发表时间: 2022-04-01 发表期刊: Nature Communications 影响因子…

新手小白学习docker第八弹------实现MySQL主从复制搭建

目录 0 引言1 实操1.1 新建主服务器容器1.2 书写配置文件1.3 重启master实例1.4 进入mysql-master容器master容器实例内创建数据同步用户 1.5 新建从服务器容器1.6 书写配置文件1.7 重启slave实例1.8 查看主从同步状态1.9 进入mysql-slave容器1.9.1 配置主从复制1.9.2 查看主从…

学习threejs,使用TWEEN插件实现动画

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.PLYLoader PLY模型加…

HarmonyOS Next星河版笔记--界面开发(5)

1.字符串 1.1.字符串拼接 作用:把两个或多个字符串,拼成一个字符串。(通常是用来拼接字符串和变量) hello world > helloworld 加好作用:拼接 let name:string 小明 console.log(简介信息,名字是 name) …

24.11.13 机器学习 特征降维(主成份分析) KNN算法 交叉验证(K-Fold) 超参数搜索

导包小总结(不全面): from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.feature_extraction import DictVectorizer(字典数据集的划分) from sklearn.feature_extraction.text import CountVectorizer(特征提取…

基于SpringBoot+RabbitMQ完成应⽤通信

前言: 经过上面俩章学习,我们已经知道Rabbit的使用方式RabbitMQ 七种工作模式介绍_rabbitmq 工作模式-CSDN博客 RabbitMQ的工作队列在Spring Boot中实现(详解常⽤的⼯作模式)-CSDN博客作为⼀个消息队列,RabbitMQ也可以⽤作应⽤程…

react+hook+vite项目使用eletron打包成桌面应用+可以热更新

使用Hooks-Admin的架构 Hooks-Admin: 🚀🚀🚀 Hooks Admin,基于 React18、React-Router V6、React-Hooks、Redux、TypeScript、Vite2、Ant-Design 开源的一套后台管理框架。https://gitee.com/HalseySpicy/Hooks-Adminexe桌面应用…

【C++】string(一)

大家好,我是苏貝,本篇博客带大家了解C的string类,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 目录 1. 标准库中的string类1.1 string类(了解)1.2 string类的常用接口说明(A) string类对象的…

新版Apache tomcat服务安装 Mac+Window双环境(笔记)

简介:Tomcat服务器器的下载和安装: 安装前提 1)电脑需要有java环境,jdk8以上,否则启动不不成功 2)已经安装Sublime⽂文件编辑软件 3)window电脑需要显示⽂文件拓拓展名 官网(https:…

see的本质是什么?

see的本质是什么?see的本质,就是一条蛇: see s蛇 e眼 e眼 ee是两只大眼睛,长在蛇的脑袋上,代表着蛇头和跟随性观察。 如果你喜欢看【龙虎斗】,看【猫蛇大战】相关的视频,你会发现&#xff0c…

0x00基础算法 -- 0x05 排序

1、离散化 排序算法的第一个应用:离散化。 “离散化”就是把无穷大(无限)的集合中的若干个(有限)元素映射为有限集合以便于统计的方法。 例如:问题的范围定义在整数集合,但是只涉及其中m个有限的…

深度学习在边缘检测中的应用及代码分析

摘要: 本文深入探讨了深度学习在边缘检测领域的应用。首先介绍了边缘检测的基本概念和传统方法的局限性,然后详细阐述了基于深度学习的边缘检测模型,包括其网络结构、训练方法和优势。文中分析了不同的深度学习架构在边缘检测中的性能表现&am…

博物馆实景复刻:开启沉浸式文化体验的新篇章

随着数字化技术的飞速发展,博物馆的展览形式正在经历一场前所未有的变革。3数字博物馆和3D线上展览,这种创新的展览方式不仅打破了时间和空间的限制,更让文化遗产的保护与传承迈上了一个新的台阶。 本文将深入探讨博物馆实景复刻虚拟展厅的兴…

服务器上安装Orcale数据库以及PL SQL工具(中文)

一、前期准备 1、oracle数据库安装包–>Oracle下载地址,版本根据当时情况就下最新的就行,下载时间可能有点长,耐心点。 2、PL SQL工具下载地址–>PL SQL下载地址,百度网盘可以共享【限速,没办法!&am…

除了 TON, 哪些公链在争夺 Telegram 用户?数据表现如何?

作者:Stella L (stellafootprint.network) 在 2024 年,区块链游戏大规模采用迎来了一个意想不到的催化剂:Telegram。随着各大公链争相布局这个拥有海量用户基础的即时通讯平台,一个核心问题浮出水面:这种用户获取策略…

JSON.stringify的应用说明

前言 JSON.stringify() 方法将 JavaScript 对象转换为字符串,在日常开发中较常用,但JSON.stringify其实有三个参数,后两个参数,使用较少,今天来介绍一下后两个参数的使用场景和示例。 语法及参数说明 JSON.stringify()&#xf…

java:接口,抽象,多态的综合小练习

package 综合抽象接口练习;public class person {protected String name;protected int age;person(){}person(String name,int age){this.namename;this.ageage;}public void setName(String name){this.namename;}public String getName(){return name;}public void setAge(i…

<AI 学习> 下载 Stable Diffusions via Windows OS

注意: 不能使用 网络路径 不再支持 HTTPS 登录,需要 Token 1. 获得合法的授权 Stability AI License — Stability AI 上面的链接打开,去申请 许可 2. 拥有 HuggingFace 账号 注册:https://huggingface.co/ 3. 配置 Tok…

【Visual Studio】设置文件目录

打开属性 输出目录:$(SolutionDir)bin\$(Platform)\$(Cinfiguration)\ 中间目录:$(SolutionDir)bin\intermediates\$(Platform)\$(Cinfiguration)\

linux病毒编写+vim shell编程

学习视频来自B站UP主泷羽sec,如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 请一定遵循《网络空间安全法》!!! Linux目录介绍 /bin 二进制可执行文件(kali里面是工具一些文件)/etc 系统的管理和配置文…