【Java】JVM(六)

news2024/10/2 12:23:39

垃圾回收

分代回收理论

当前商业虚拟机的垃圾回收器,大多遵循“分代收集”的理论来进行设计,这个理论大体上是这么描述的:

1、绝大部分的对象都是朝生夕死。

2、熬过多次垃圾回收的对象就越难回收。

根据以上两个理论,朝生夕死的对象放一个区域,难回收的对象放另外一个区域,这个就构成了新生代和老年代。

在这里插入图片描述

GC分类

1、新生代回收(Minor GC/Young GC):指只是进行新生代的回收。

2、老年代回收(Major GC/Old GC):指只是进行老年代的回收。目前只有CMS垃圾回收器会有这个单独的回收老年代的行为。
(Major GC定义是比较混乱,有说指是老年代,有的说是做整个堆的收集,这个需要你根据别人的场景来定,没有固定的说法)

3、整堆回收(Full GC):收集整个Java堆和方法区(注意包含方法区)

垃圾回收算法

复制算法(Copying)

将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要按顺序分配内存即可,实现简单,运行高效。只是这种算法的代价是将内存缩小为了原来的一半。

但是要注意:内存移动是必须实打实的移动(复制),所以对应的引用(直接指针)需要调整。

复制回收算法适合于新生代,因为大部分对象朝生夕死,那么复制过去的对象比较少,效率自然就高,另外一半的一次性清理是很快的。

在这里插入图片描述

Appel式回收

一种更加优化的复制回收分代策略:具体做法是分配一块较大的Eden区和两块较小的Survivor空间(你可以叫做From或者To,也可以叫做Survivor1和Survivor2)

专门研究表明,新生代中的对象98%是“朝生夕死”的,所以并不需要按照1:1的比例来划分内存空间,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor[1]。当回收时,将Eden和Survivor中还存活着的对象一次性地复制到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间。

HotSpot虚拟机默认Eden和Survivor的大小比例是8:1,也就是每次新生代中可用内存空间为整个新生代容量的90%(80%+10%),只有10%的内存会被“浪费”。当然,98%的对象可回收只是一般场景下的数据,我们没有办法保证每次回收都只有不多于10%的对象存活,当Survivor空间不够用时,需要依赖其他内存(这里指老年代)进行分配担保(Handle Promotion)

在这里插入图片描述

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

算法分为“标记”和“清除”两个阶段:首先扫描所有对象标记出需要回收的对象,在标记完成后扫描回收所有被标记的对象,所以需要扫描两遍。

回收效率略低,如果大部分对象是朝生夕死,那么回收效率降低,因为需要大量标记对象和回收对象,对比复制回收效率要低。

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

回收的时候如果需要回收的对象越多,需要做的标记和清除的工作越多,所以标记清除算法适用于老年代。

在这里插入图片描述

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

首先标记出所有需要回收的对象,在标记完成后,后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。标记整理算法虽然没有内存碎片,但是效率偏低。

我们看到标记整理与标记清除算法的区别主要在于对象的移动。对象移动不单单会加重系统负担,同时需要全程暂停用户线程才能进行,同时所有引用对象的地方都需要更新(直接指针需要调整)。

所以看到,老年代采用的标记整理算法与标记清除算法,各有优点,各有缺点。

在这里插入图片描述

JVM中常见的垃圾回收器

在新生代中,每次垃圾回收时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成回收。

而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记—清理”或者“标记—整理”算法来进行回收。

在这里插入图片描述

Serial/Serial Old

JVM刚诞生就只有这种,最古老的,单线程,独占式,成熟,适合单CPU,一般用在客户端模式下。

这种垃圾回收器只适合几十兆到一两百兆的堆空间进行垃圾回收(可以控制停顿时间再100ms左右),但是对于超过这个大小的内存回收速度很慢,所以对于现在来说这个垃圾回收器已经是一个鸡肋。

在这里插入图片描述

Stop The World(STW)

单线程进行垃圾回收时,必须暂停所有的工作线程,直到它回收结束。这个暂停称之为“Stop The World”,但是这种STW带来了恶劣的用户体验,例如:应用每运行一个小时就需要暂停响应5分。这个也是早期JVM和java被C/C++语言诟病性能差的一个重要原因。所以JVM开发团队一直努力消除或降低STW的时间。

Parallel Scavenge(ParallerGC)/Parallel Old

为了提高回收效率,从JDK1.3开始,JVM使用了多线程的垃圾回收机制,关注吞吐量的垃圾收集器,高吞吐量则可以高效率地利用CPU时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。

所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间),虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。

该垃圾回收器适合回收堆空间上百兆~几个G。

ParNew

多线程垃圾回收器,与CMS进行配合,对于CMS(CMS只回收老年代),新生代垃圾回收器只有Serial与ParNew可以选。和Serial基本没区别,唯一的区别:多线程,多CPU的,停顿时间比Serial少。(在JDK9以后,把ParNew合并到了CMS了)

Concurrent Mark Sweep (CMS)

在这里插入图片描述

回收过程

收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器就非常符合这类应用的需求。

从名字(包含“Mark Sweep”)上就可以看出,CMS收集器是基于“标记—清除”算法实现的,它的运作过程相对于前面几种收集器来说更复杂一些,

整个过程分为4个步骤,包括:

初始标记
短暂,仅仅只是标记一下GC Roots能直接关联到的对象,速度很快。

并发标记
和用户的应用程序同时进行,进行GC Roots追踪的过程,标记从GCRoots开始关联的所有对象开始遍历整个可达分析路径的对象。这个时间比较长,所以采用并发处理(垃圾回收器线程和用户线程同时工作)

重新标记
短暂,为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。

并发清除

由于整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以,从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。

CM回收器的问题

CPU敏感:CMS对处理器资源敏感,毕竟采用了并发的收集、当处理核心数不足4个时,CMS对用户的影响较大。

浮动垃圾:由于CMS并发清理阶段用户线程还在运行着,伴随程序运行自然就还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC时再清理掉。这一部分垃圾就称为“浮动垃圾”。

由于浮动垃圾的存在,因此需要预留出一部分内存,意味着 CMS 收集不能像其它收集器那样等待老年代快满的时候再回收。

会产生空间碎片:标记 - 清除算法会导致产生不连续的空间碎片。

碎片带来了两个问题:

效率问题

1、空间分配效率较低:
如果是连续的空间 JVM 可以通过使用指针碰撞的方式来分配,而对于这种有大量碎片的空闲链表则需要逐个访问空闲列表中的项来访问,查找可以存放新建对象的地址。

2、空间利用效率变低:
新生代晋升的对象大小大于了连续空间的大小,即使整个 Old 区的容量是足够的,但由于其不连续,也无法存放新对象。就是内存碎片导致的 Promotion Failed,Young GC 以为 Old 有足够的空间,结果到分配时,晋级的大对象找不到连续的空间存放。

垃圾回收器退化

如果发生了,Promotion Failed,那么CMS会退化,单线程串行 GC 模式,一般会使用Serial Old ,因为Serial Old是一个单线程,所以如果内存空间很大、且对象较多时,CMS发生这样情况会很卡。
Serial使用使用标记整理算法,单线程全暂停的方式,对整个堆进行垃圾收集,暂停时间要长于 CMS。

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

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

相关文章

【Java】JVM学习(四)

对象的分配 JVM中对象的创建过程 对象的内存分配 虚拟机遇到一条new指令时,首先检查是否被类加载器加载,如果没有,那必须先执行相应的类加载过程。 类加载就是把class加载到JVM的运行时数据区的过程。 1)检查加载 首先检查这…

从选题、创作、编辑、推广到优化,23个必用的内容营销工具

咱们做内容营销的,要懂营销懂产品,看得懂技术语言,写得了行业洞察,做出来的内容要有创意还要接地气,专业内容也不能落下,除了会写,还要会运营会设计会剪视频,简直就是全才嘛。 但是…

你知道游戏配音怎么制作吗?教你游戏配音教程怎么做

曾经,有一个叫小明的游戏迷,他对于游戏世界充满了热爱和想象。每当他控制着自己喜爱的角色在游戏中冒险时,他总是希望能够为这些角色赋予独特的声音,让它们真正活起来。然而,他却面临一个问题:游戏配音教程…

【CTF-Reverse中的加密算法】密码算法特征识别,变种密码算法分析

上一章中我们带领大家了解了加密算法——RC4,TEA,Base64算法的原理,但是加密算法远不止这些,需要大家自行去学习,在这一章中,我来带领大家了解密码算法特征识别,变种密码算法分析。 一.密码算法特征识别 1.什么是特征…

详解MySQL的常用数据类型

文章目录 一、MySQL 数据类型1.1、mysql中编码和字符 二、数值类型2.1、整数类型的长度2.2、浮点型 三、字符串类型3.1、字符串类型长度 四、日期和时间类型4.1、DATETIME 五、二进制数据类型六、使用建议 一、MySQL 数据类型 MySQL支持很多数据类型,以便我们能在复…

实现定时任务

1 问题 定时任务中,每天统计一下今日博客的各项数据,并以邮件的形式发送给自己。 2 方法 .首先在某目录下新建任务文件 crontest.cron,用于存在定时任务语句。.相同目录新建 hello.py 文件,并且编辑这个文件写一句简单的 print(He…

【JUC进阶】05. 偏向锁

目录 1、前言 2、偏向锁 2.1、基本原理 2.2、使用场景 3、获取偏向锁 4、何时撤销 4.1、到达安全点 4.2、其他线程尝试竞争偏向锁 4.3、重新计算hashcode 5、小结 1、前言 偏向锁是Java并发编程中一种重要的锁机制,它针对特定的线程进行优化,…

项目集活动—项目集收尾阶段活动

项目集收尾阶段活动从项目集组件完成了所有输出的交付,且项目集开始交付预期效益。某些情况下,项目集治理可能决定在所有组件完成之前就提前执行项目集收尾。无论哪种情况,此阶段项目集活动的目标都是释放项目集资源,支持将剩余项…

区分BOM和DOM,区分window、document、html、body

https://blog.csdn.net/xswl134679/article/details/128795161 JavaScript三大组成部分 1. ECMAScript ECMAScript是JavaScript的语法标准,由ECMA(欧洲计算机厂家协会)制定的。 2. BOM BOM即浏览器对象模型(brower object mode…

Contrastive Learning in Image (CVPR 2023)

文章目录 1. Open Vocabulary Semantic Segmentation with Patch Aligned Contrastive Learning (图文匹配)1.目标2.任务类型3.解决思路4. 总结 2. MaskCLIP: Masked Self-Distillation Advances Contrastive Language-Image Pretraining (图…

数学模型在水环境评价、防洪评价、排污口论证、水质、水量、水生态、水动力等方面的应用

目录 专题一、一维水动力模型模拟一河道水流的应用 专题二、一维复杂河网模型构建及建筑物设置 专题三、一维水质模型在环境影响评价中的应用 专题四、平面二维水动力模型的构建河验证 专题五、平面二维水动力模型在防洪影响评价中的应用 专题六、平面二维水动力水质模型…

抖音kol投放模型怎么打造,营销策略规划

这是一个内容为王的时代,想要在小红书这种内容平台做好内容营销,一定要了解抖音kol投放模型怎么打造,营销策略规划。 一、如何进行kol投放 品牌想要完成一次高效而准确的完成kol投放模型,需要完整的品牌投放策略。针对于小红书平台…

如何驯化机器狗读懂人类手势,手把手教你!

作为全国普通高校大学生竞赛榜单内竞赛,“中国软件杯”大学生软件设计大赛-智能四足机器狗电力巡检系统开发赛项,目前已吸引了全国2041支队伍参加。经过激烈的目标检测与分割算法打榜赛,最终,有153支团队成功晋级区域赛。在即将于…

知乎财报预测:知乎2023年Q2收入将继续下滑,净亏损将扩大一倍

来源:猛兽财经 作者:猛兽财经 华尔街分析师对知乎2023年第二季度财报的预测 在5月24日发布第一季度业绩时,知乎(ZH)并未对2023年第二季度或2023财年全年提供任何具体的指引。但目前卖方分析师的一致财务预测表明&…

F-35飞控系统详解

基于非线性动态逆(NDI)的控制律 1. F-35飞控控制律 F-35采用了由三台冗余机载管理计算机(VMC,Vehicle Management Computers)中运行的非线性动态逆控制架构来提供电传飞行控制。F-35的控制律不仅能增强飞机动力学特性实现增稳,还…

java学习记录之JDBC2

1 JDBC回顾  Statement 语句执行者 Connection conn null; Statement st null; ResultSet rs null; try{ //1 通过工具类获得连接 conn JdbcUtils.getConnection(); //2 获得语句执行者 st conn.createStatement() --> 参数 结果集类型、并发参数 (滚动结…

如何在 Spring Boot 中使用定时任务

如何在 Spring Boot 中使用定时任务 引言 在实际的项目中,我们经常需要编写定时任务来执行一些周期性的任务,比如定时备份数据库、定时发送邮件等。在 Spring Boot 中,我们可以使用 Spring 的 Task Execution 和 Scheduling 来实现定时任务…

用BERT做命名实体识别任务

命名实体识别NER任务是NLP的一个常见任务, 它是Named Entity Recognization的简称。 简单地说,就是识别一个句子中的各种 名称实体。 诸如:人名,地名,机构 等。 例如对于下面这句话: 小明对小红说:"你…

佩戴舒适度的蓝牙耳机品牌有哪些?佩戴舒适性蓝牙耳机排行榜推荐

​对于年轻人来说,耳机使用场景丰富,时尚追求度高,喜好的音乐类型也是多种多样,需求侧重也不尽相同。下面我来推荐几款相当不错的蓝牙耳机给大家,总会有喜欢那款! 一、南卡OE PRO开放式耳机 南卡OE PRO是国…

带你阅读 Flutter Demo(flutter 保姆级入门教程)

dart、flutter Flutter Demo 解析 - 文章信息 - Author: Jack Lee (jcLee95) Visit me at: https://jclee95.blog.csdn.netEmail: 291148484163.com. Shenzhen ChineAddress of this article:https://blog.csdn.net/qq_28550263/article/details/xxxxxx 【介绍】:本…