JVM_垃圾收集器详解

1、 前言

JVM就是Java虚拟机,说白了就是为了屏蔽底层操作系统的不一致而设计出来的一个虚拟机,让用户更加专注上层,而不用在乎下层的一个产品。这就是JVM的跨平台,一次编译,到处运行。
而JVM中的核心功能其实就是自动化的垃圾回收机制。

在Java中你使用对象,使用内存,不用担心回收,只管new对象就行了,不用管垃圾的回收。
因为Java当中是自动化的垃圾回收机制。JVM有专门的垃圾回收器,把垃圾回收这件事给干了。

2、分代收集理论

当前虚拟机的垃圾收集都采用分代收集算法,根据对象存活周期的不同将内存分为几块。一般将java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。
新生代:每次收集都会有大量对象(近99%)死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。就比如新生代中的 S0 和 S1 区域。

老年代:对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。

PS:标记-清除”或“标记-整理”算法会比复制算法慢10倍以上。

2.1、垃圾收集算法

标记-复制算法

标记-复制算法是把内存分为大小相等的两块,每次使用其中的一块,当这块内存使用完以后,就会把还存活的对象放到另外一块内存中去,清理刚才使用到的那块空间。分为标记和复制两个阶段:

第一阶段:标记;就是根据Gc Roots标记存活的对象。
第二阶段:复制;把存活的对象复制到另外一块内存中。
缺点:会浪费多余的存储空间。

2.2、标记-清除算法

标记-清除算法分为标记和清除两个阶段:
第一阶段:标记;就是根据Gc Roots标记存活的对象。
第二阶段:清除;统一回收未被标记的对象。

缺点:
效率问题 (如果需要标记的对象太多,效率不高) ;
空间问题(标记清除后会产生大量不连续的碎片)。

 2.3、标记-整理算法

标记-整理算法是根据老年代的特点设计出的一种标记算法。他的标记过程和标记清除算法一样的,后续不同的是,它会先把所有存活的对象规整的移动到一起,然后把边界外的对象统一回收。

3、垃圾回收中的STW

对于Java项目来说,JVM进行垃圾收集会有一个很大的问题,就是STW(Stop The World)。
就是在垃圾回收的时候会把应用线程(项目中运行的线程)给停止,然后进行垃圾回收,如果STW的时间过程,用户就会感觉到明显的卡顿现象。

3.1、STW带来的问题

1)安卓手机系统的卡顿
Google 主导的 Android 系统需要解决的一大问题就是显示卡顿问题,通过对 GC 算法的不断演进,停顿时间控制在几个ms 级别。所以这也是Android与苹果IOS系统竞争的一大利器。
2)证券交易系统的实时性
证券交易系统的实时性要求很高,一般都是需要低卖高卖,差之毫厘谬以千里,如果STW的时间很长,到达几秒钟的级别,这几秒钟后的市场完全不同了。所以用Java来做证券系统,STW的时间越短越好。

3.2、垃圾收集器的发展

为了满足不同的业务场景,Java的GC算法和垃圾收集器都在不同的迭代,对于这些延迟敏感的应用来说,GC停顿已经成为了阻碍Java发展的一大顽疾。

近些年来,服务器的性能越来越好,各种应用可以使用的堆内存也越来越大,其实垃圾收集器的发展都是为了解决STW的停顿时间而一直迭代。为了让STW的停顿时间也跟随着堆大小的增长而不呈现指数级的增长而努力,推出了一系列垃圾收集器。

4、垃圾收集器

如果说垃圾回收算法是内存收回的理论,那么垃圾收集器就是内存回收的具体实现。
虽然我们对各个收集器进行比较,但并非为了挑选出一个最好的收集器。因为直到现在为止还没有最好的垃圾收集器出现,更加没有万能的垃圾收集器, 我们能做的就是根据具体应用场景选择适合自己的垃圾收集器 。

4.1、单线程垃圾收集器

1)Serial

Serial(串行)垃圾收集器,一看名字就知道它是一个单线程收集器。它的单线程的意义不仅仅意味着它只会使用一条垃圾收集线程去完成垃圾手机工作,更重要的是它在进行垃圾手机工作的时候还必须暂停其他的所有工作线程(STW),直到它收集结束。

新生代采用标记-复制算法,老年代采用标记-整理算法。

Serial 虽然是单线程,STW的时间有点长,但是它简单且高效(与其它垃圾收集器相比),它没有线程交互的开销,自然而然的可以获得很高的单线程收集效率。

参数设置:-XX:+UseSerialGC(年轻代)  -XX:+UseSerialOldGC(老年代)

2)Serial Old
Serial Old收集器是Serial收集器的老年代版本,它同样是单线程收集器。
两大用途:
一种用途是在JDK1.5 以及以前的版本中与Parallel Scavenge收集器搭配使用。
一种用途是作为CMS收集器的后备方案。

4.2、多线程垃圾收集器

1)Parallel Scavenge

Parallel收集器是Serial收集器的多线程版本,除了使用多线程垃圾收集以外,其余和Serial收集器类似。默认的收集线程数跟cpu核数相同,当然也可以用参数(-XX:ParallelGCThreads)指定收集线程数,但是一般不推荐修改。

Parallel Scavenge收集器关注点是吞吐量(高效率的利用CPU)。所谓吞吐量就是CPU中用于运行用户代码的时间与CPU总消耗时间的比值。

新生代采用标记-复制算法,老年代采用标记-整理算法。参数设置:-XX:+UseParallelGC(年轻代),-XX:+UseParallelOldGC(老年代)

2)Parallel Old
Parallel Old收集器是Parallel Scavenge收集器的老年代版本。
使用多线程和“标记-整理”算法。在注重吞吐量以及 CPU资源的场合,都可以优先考虑 Parallel Scavenge收集器和Parallel Old收集器(JDK8默认的新生代和老年代收集器)。

3)ParNew

ParNew收集器其实跟Parallel收集器很类似,区别主要在于它可以和CMS收集器配合使用。
新生代采用标记-复制算法,老年代采用标记-整理算法。
参数设置:-XX:+UseParNewGC

4.3、多线程+并发收集器

1)CMS
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户体 验的应用上使用,它是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。
从它的名字中可以看出它是一种 “标记-清除” 算法的实现

GC步骤:

初始标记(STW):暂停所有的其它线程,期间会STW,并记录GC Roots直接能引用的对象,速度很快。
并发标记:并发标记阶段就是从GC Roots的直接关联对象开始遍历整个对象图的过程, 这个过程耗时较长但 是不需要停顿用户线程, 可以与垃圾收集线程一起并发运行。因为用户程序继续运行,可能会有导致已经标记过的对象状态发生改变。
重新标记(STW):重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。主要用到三色标记里的增量更新算法做重新标记。
并发清理:开启用户线程,同时GC线程开始对未标记的区域做清扫。这个阶段如果有新增对象会被标记为黑色不做任何处理。
并发重置:重置本次GC过程中的标记数据。
优点:并发收集、低停顿。

缺点:
对CPU资源敏感(会和服务抢资源);
无法处理浮动垃圾(在并发标记和并发清理阶段又产生垃圾,这种浮动垃圾只能等到下一次gc再清理了);
它使用的回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生,当然通过参数(- XX:+UseCMSCompactAtFullCollection)可以让jvm在执行完标记清除后再做整理 。
执行过程中的不确定性,会存在上一次垃圾回收还没执行完,然后垃圾回收又被触发的情况,特别是在并 发标记和并发清理阶段会出现,一边回收,系统一边运行,也许没回收完就再次触发full gc,也就是"concurrent mode failure",此时会进入STW,用serial old垃圾收集器来回收。

核心参数设置:
参数 含义

-XX:+UseConcMarkSweepGC	启用CMS
-XX:ConcGCThreads	并发的GC线程数
-XX:+UseCMSCompactAtFullCollection	FullGC之后做压缩整理(减少碎片)
-XX:CMSFullGCsBeforeCompaction	多少次FullGC之后压缩一次,默认是0,代表每次FullGC后都会压缩一次
-XX:CMSInitiatingOccupancyFraction	当老年代使用达到该比例时会触发FullGC(默认是92,这是百分比)
-XX:+UseCMSInitiatingOccupancyOnly	
只使用设定的回收阈值
(-XX:CMSInitiatingOccupancyFraction设定的值),如果不指定,JVM仅在第一次使用设定值,后续则会自动调整 
-XX:+CMSScavengeBeforeRemark	在CMS GC前启动一次minor gc,目的在于减少老年代对年轻代的引 用,降低CMS GC的标记阶段时的开销,一般CMS的GC耗时 80%都在标记阶段
-XX:+CMSParallellnitialMarkEnabled	表示在初始标记的时候多线程执行,缩短STW
-XX:+CMSParallelRemarkEnabled	在重新标记的时候多线程执行,缩短STW

4.4、G1收集器

G1垃圾收集器的工作原理和特性‌:

G1垃圾收集器是一种面向服务器的垃圾收集器,它将堆划分为多个大小相等的独立区域(Region),这些Region可以是年轻代或老年代。G1保留了年轻代和老年代的概念,但它们不再是物理隔阂,而是Region的集合。G1通过监视应用程序的行为和垃圾收集暂停信息来建立相关成本模型,以实现可预测的暂停时间目标。它采用分步递增和并行的方式来执行空间回收,以缩短停顿时间‌。

大内存应用‌:G1垃圾收集器适用于堆大小约为6GB或更大的应用程序。当堆大小超过50%的Java堆内存被实时数据占用时,G1能够提供更好的性能‌。

多处理器机器‌:G1垃圾收集器特别适合配备多颗处理器的服务器,因为它能够利用多核处理器的优势,实现高效的垃圾收集‌。

需要稳定且可预测的暂停时间‌:G1垃圾收集器旨在实现稳定的暂停时间目标,通常不超过0.5秒,这对于需要低延迟的应用程序非常重要‌。

对象分配和晋升速率变化显著‌:在堆中,对象分配和晋升的速率可能会随时间显著变化,G1能够适应这种变化,提供更好的性能‌。

存在大量碎片‌:当堆中存在大量碎片时,G1能够通过分步递增和并行的方式来执行空间回收,减少碎片化对性能的影响‌。

使用G1垃圾收集器的命令行参数‌:

-XX:+UseG1GC:显式启用G1垃圾收集器。

-XX:G1HeapRegionSize:手动指定Region的大小。

-XX:G1NewSizePercent:设置新生代初始占比。

-XX:G1MaxNewSizePercent:调整新生代的最大占比。

这些参数可以帮助用户根据具体需求调整G1垃圾收集器的行为,以优化应用程序的性能和暂停时间‌。

4.5、ZGC

jdk11 低延迟,浮动垃圾多,适合几百G 以上

5 总结

本章主要讲了JVM中垃圾收集器的发展,从单线程到多线程,再到GC线程和用户线程并发收集的垃圾收集器。
如何选择垃圾收集器:
优先调整堆的大小让服务器自己来选择
如果内存小于100M,使用串行收集器
如果是单核,并且没有停顿时间的要求,串行或JVM自己选择
如果允许停顿时间超过1秒,选择并行或者JVM自己选
如果响应时间最重要,并且不能超过1秒,使用并发收集器
4G以下可以用parallel,4-8G可以用ParNew+CMS,8G以上可以用G1,几百G以上用ZGC。

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

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

相关文章

Android音频框架总结

1、AudioFlinger:接收多个APP的数据,合并下发;是策略的执行者,例如具体如何与音频设备通信,如何维护现有系统中的音频设备,以及多个音频流的混音如何处理等等都得由它来完 成。 AudioFlinger主要包含3个主…

深度学习:自然语言处理

一、引言 自然语言处理作为人工智能领域的关键分支,致力于使计算机能够理解、分析和生成人类语言。近年来,随着深度学习技术的迅猛发展,自然语言处理取得了前所未有的突破,一系列创新技术和应用不断涌现,极大地推动了…

网络安全-安全散列函数,信息摘要SHA-1,MD5原理

安全散列函数 单向散列函数或者安全散列函数之所以重要,不仅在于消息认证(消息摘要。数据指纹)。还有数字签名(加强版的消息认证)和验证数据的完整性。常见的单向散列函数有MD5和SHA 散列函数的要求 散列函数的目的是文件、消息或者其它数据…

java基础知识(常用类)

目录 一、包装类(Wrapper) (1)包装类与基本数据的转换 (2)包装类与String类型的转换 (3)Integer类和Character类常用的方法 二、String类 (1)String类介绍 1)String 对象用于保存字符串,也就是一组字符序列 2)字符串常量对象是用双引号括起的字符序列。例如:&quo…

音视频基础扫盲之认识PCM(Pulse Code Modulation,脉冲编码调制)

PCM(Pulse Code Modulation,脉冲编码调制)一种用数字表示采样模拟信号的方法。是用于将波形表示的模拟音频信号转换为数字1和0表示的数字音频信号,而不压缩也不丢失信息的处理技术。PCM编码的最大的优点就是音质好,最大…

【Zookeeper】四,Zookeeper节点类型、通知、仲裁、会话

文章目录 Zookeeper的架构znode的版本Zookeeper的节点类型层级树状结构znode的不同类型 Zookeeper监视与通知通知的类型 Zookeeper的仲裁Zk的会话会话的生命周期 Zookeeper的架构 Zookeeper的服务器端运行两种模式:独立模式(standalone)和仲…

unity | 动画模块之卡片堆叠切换

一、预览动画 可以放很多图,可以自己往后加,可以调图片x轴和y轴间距,可以调图片飞出方向,可以调堆叠方向。 图1 图片堆叠动画预览 二、纯净代码 有粉丝问我这个效果,最近很忙,没有时间细写,先…

Python开发环境搭建+conda管理环境

下载Miniconda 推荐从清华镜像下载安装包 Index of /anaconda/miniconda/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 打开网页后,下拉到最后找到Miniconda3-latest前缀的文件,或者网页中直接搜索Miniconda3-latest,都可以找…

Git——本地仓库链接并推送到多个远程仓库

步骤 1. 新建仓库init 或 删除已有仓库远程链接 // 1.新建init git init// 2.已有仓库,查看链接的远程仓库 git remote -v// 3.已有远程连接仓库,需要删除连接 git remote rm origin(或对应远程仓库名) 2.新建远程仓库 在gitee、github等托管平台创建…

shell脚本基础学习_总结篇(完结)

细致观看可以,访问shell脚本学习专栏,对应章节会有配图https://blog.csdn.net/2201_75446043/category_12833287.html?spm1001.2014.3001.5482 导语 一、shell脚本简介 1. 定义: 2. 主要特点: 3. shell脚本的基本结构 4. S…

Ubuntu20.04+ROS 进行机械臂抓取仿真:环境搭建(一)

目录 一、从官网上下载UR机械臂 二、给UR机械臂添加夹爪 三、报错解决 本文详细介绍如何在Ubuntu20.04ROS环境中为Universal Robots的UR机械臂添加夹爪。首先从官方和第三方源下载必要的软件包,包括UR机械臂驱动、夹爪插件和相关依赖。然后,针对gazeb…

23省赛区块链应用与维护(房屋租凭【下】)

23省赛区块链应用与维护(房屋租凭) 背景描述 随着异地务工人员的增多,房屋租赁成为一个广阔市场。目前,现有技术中的房屋租赁是由房主发布租赁信息,租赁信息发布在房屋中介或租赁软件,租客获取租赁信息后,现场看房,并签订纸质的房屋租赁合同,房屋租赁费用通过中介或…

数字化转型的架构蓝图:从理论到实践的全面指导

在数字经济的高速发展中,企业正面临全新的竞争压力。为了在数字化浪潮中保持竞争力,许多企业都在寻求一种系统化的方法来实现其数字化转型。这种变革不仅涉及技术创新,还包括业务流程的彻底重塑与组织文化的转型。要成功实现数字化转型&#…

关于node全栈项目打包发布linux项目问题总集

1.用pm2部署nest 说明:如果一开始将nest直接打包放到linux服务器上用pm2执行则会报错,这是因为tsconfig.build.tsbuildinfo文件的路径以及相关依赖问题。 报错会为:什么东西找不到.... 所以建议以下为步骤一步一步配置 将整个nest添加压缩包直…

实验三 z变换及离散时间LTI系统的z域分析

实验原理 有理函数z 变换的部分分式展开 【实例2-1】试用Matlab 命令对函数 X ( z ) 18 18 3 − 1 − 4 z − 2 − z − 3 X\left(z\right)\frac{18}{183^{-1} -4z^{-2} -z^{-3} } X(z)183−1−4z−2−z−318​ 进行部分分式展开,并求出其z 反变换。 B[18]; A…

sed awk 第二版学习(十一)—— 交互式拼写检查器 spellcheck.awk

目录 1. 脚本代码 2. 执行情况 3. 代码详解 (1)BEGIN 过程 (2)主过程 (3)END 过程 (4)支持函数 4. 附加说明 这是一个基于 UNIX spell 程序的名为 spellcheck 的 awk 脚本&a…

开源 AI 智能名片 2 + 1 链动模式 S2B2C 商城小程序源码助力品牌共建:价值、策略与实践

摘要:在当今数字化商业环境下,品牌构建已演变为企业与消费者深度共建的过程。本文聚焦于“开源 AI 智能名片 2 1 链动模式 S2B2C 商城小程序源码”,探讨其如何融入品牌建设,通过剖析品牌价值构成,阐述该技术工具在助力…

基于Springboot的流浪宠物管理系统

基于javaweb的流浪宠物管理系统 介绍 基于javaweb的流浪宠物管理系统的设计与实现,后端框架使用Springbootmybatis,前端框架使用Vuehrml,数据库使用mysql,使用B/S架构实现前台用户系统和后台管理员系统,和不同权限级别…

深度学习与持续学习:人工智能的未来与研究方向

文章目录 1. 持续学习与深度学习1.1 深度学习的局限1.2 持续学习的定义 2. 目标与心智2.1 奖励假说2.2 心智的构成 3. 对研究方法的建议3.1 日常写作记录3.2 中立对待流行趋势 1. 持续学习与深度学习 1.1 深度学习的局限 深度学习注重“瞬时学习”,如ChatGPT虽在语…

Pod 动态分配存储空间实现持久化存储

配置 Pod 以使用 PersistentVolume 作为存储 ​ 关于持久卷的介绍,可以看官方文档 https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/ ​ 持久卷根据存储位置,可以使用本地存储和云存储,如果有云服务平台&#xff0c…