JVM——垃圾回收器G1+垃圾回收调优
4.4 G1(一个垃圾回收器)
定义:
取代了CMS垃圾回收器。和CMS一样时并发的。
适用场景:
物理上分区,逻辑上分代。
相关JVM参数:
- -XX:+UseG1GC
- -XX:G1HeapRegionSize=size
- -XX:MaxGCPauseMillis=time
1) G1 垃圾回收阶段
三个回收阶段,第一个是新生代回收,第二个是新生代+CM,第三个是混合回收。
当老年代内存超过阈值,会在新生代垃圾回收时进行并发标记。然后混合收集阶段会对新生代和老年代都进行收集。
Mixed GC:收集整个新生代和部分老年代的垃圾收集,目前只有G1有这种行为
2) Young Collection(新生代回收)
新生代内存布局如上。
G1会把内存划分成大小相同的区域,每个区域都可以独立作为伊甸园,幸存区的,老年代。
白色的都是空闲区域,新创建的对象都在eden区,图上的E。
当Eden区被占满就会触发垃圾回收并STW(砸瓦鲁多)。
垃圾回收时把对象通过copy算法复制进幸存区。
当幸存区对象过多或是对象年龄达到阈值就又会触发新生代垃圾回收,幸存区对象部分晋升到老年代,不够年龄的对象会拷贝到另一个幸存区。
3) Young Collection + CM(新生代回收+CM)
- 在Young GC 时会进行 GC Root 的初始标记
- 老年代占用堆空间比例达到闻值时,进行并发标记 (不会 STW),由下面的JVM 参数决定
- -XX:InitiatingHeapOccupancyPercent=percent (默认45%)
4) Mixed Collection(混合回收)
会对 E、S、o 进行全面垃圾回收
- 最终标记 (Remark)会 STW (解决并发标记阶段产生的垃圾和问题)
- 拷贝存活(Evacuation)会STW ()
-XX:MaxGCPauseMillis=ms
混合收集时新生代垃圾回收和之前一样,该复制的赋值,该晋升的晋升。
老年代垃圾回收会把根据设定参数最大暂停时间进行有选择的垃圾回收: 那些内存超过阈值的老年代也会复制到别的老年代区域。堆内存较大,老年代垃圾回收因为复制时间较长,会超过最大暂停时间,所以G1会挑出回收价值最高部分(释放内存多)的区域。
5) Full GC概念辨析
SerialGC(串行)
- 新生代内存不足发生的垃圾收集 - minor gc
- 老年代内存不足发生的垃圾收集 - ful gc
ParallelGC(并行)
- 新生代内存不足发生的垃圾收集 - minor gc
- 老年代内存不足发生的垃圾收集 - full gc
CMS (并发)
- 新生代内存不足发生的垃圾收集 - minor gc
- 老年代内存不足
G1 (并发)
- 新生代内存不足发生的垃圾收集 - minor gc
- 老年代内存不足
四个垃圾收集器在新生代内存不足时都会触发minor gc。
G1在垃圾回收速度跟不上垃圾产生的速度,并发收集失败,退化为多线程full GC。CMS是单线程full GC。
CMS和G1在回收速度高于产生速度时不会有Full GC。
6) Young Collection 跨代引用
在新生代垃圾回收查找根对象时,部分对象来自老年代。老年代存活对象非常多,要遍历查找的话效率低下,因此采用卡表的技术,将老年代区域再次细分。如果老年代其中有个对象应用了新生代对象,对应的卡标记为脏卡。
好处:找GC Root不需要遍历整个老年代,利于提高效率
新生代中有Remembered Set记录外部对它的引用,记录有哪些脏卡区域。
引用变更会由单独线程进行工作
7) Remark(重新标记)
在CMS中有并发标记阶段和重新标记阶段。
上图是并发标记阶段时对象的处理状态,黑色是已经处理完成,会被保留的,灰色是正在处理,白色的是尚未处理。
有引用的灰色和白色都会存活,没有引用的白色会被当垃圾回收。
在并发标记阶段处理时,用户线程改变了对c的引用,导致处理C时会将其标记成白色,结束后被当成垃圾回收。
别的情况:
c被处理完后,用户线程又改变了c的引用地址,但是A已经是黑色,不会再顺着A处理C. 所以并发标记结束后C依旧被认为是白色的,这是不对的。
这里要对对象的应用做进一步检查就是Remark(重新标记阶段)。
做法:
当对象引用发生改变时,写屏障代码将会执行。如上所示c被A引用后会将C放入一个队列并置为灰色。进入重新标记阶段会STW,然后将队列中对象进行检查,发现有强引用就会将其变成黑色。
写屏障技术,加入satb_mark_queue队列
8)JDK 8u20 宁符串去重(优化)
jdk8中底层使用char数组存储每个String对象,如果有大量new String动作会导致内存占用提高,然后就要进行去重。除了使用之前的intern()方法进行去重。G1有了别的去重方法。
默认开启这个去重方法
9)DK 8u40 并发标记类卸载
条件如上:类的实例都被回收了,某个类加载器的所有类都不再使用。
jdk的类加载器一般不会被卸载,jdk的一般都是启动类加载器,扩展类加载器,应用的程序类加载器始终存在。对于自定义的类加载有卸载需求。
10)JDK 8u60 回收巨型对象
在G1的区域有四种区(伊甸园,幸存区,老年代区),还有这里的巨型对象区。
分布如下,可能占用多个region.
当如下图所示,某个的巨型对象没有被老年代引用时就可以回收了,目的就是尽早回收巨型对象。
11)DK 9 并发标记起始时间的调整
G1 垃圾回收器也有一个full GC问题,垃圾回收速度跟不上垃圾产生速度也会退化为full GC。
避免方法:
提前让垃圾回收开始,让混合收集提前开始,减少full GC发生几率。
jdk9之前要设定老年内存占比阈值。
让空挡空间足够大,能够容纳并发阶段产生的浮动垃圾,避免full GC发生。???????
这句话有点问题??/
12)JDK 9 更高效的回收
- 250+增强
- 180+bug修复
- Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide, Release 12
现在最新都是ZCG了.....还好大多数企业还是jdk8或者jdk11
5.垃圾回收调优
JDK 11 Documentation - Books
使用该命令看到了虚拟机GC相关参数
jmap jconsle MAT等工具
5.1 调优领域
垃圾回收调优近似众多调优的一个方向。GC的影响明显而已。
多个别的领域如下
5.2确定目标
cms g1 zgc低延迟,paralle1gc吞吐量
选择不同的垃圾回收器
5.3 最快的 GC 是不发生 GC
GC频繁就要考虑是否代码有问题。
在resultSet里设置mysql查询会导致大量数据加载到堆内存,导致gc频繁,甚至导致内存溢出,应该加以限制。避免无用数据都放在java内存里
缓存实现可以使用如Redis等第三方缓存。
5.4 新生代调优
上面是排除所有代码问题,下面才是内存调优。
建议都要从新生代开始。
每个线程在伊甸园中都会有一块私有区域叫做TLAB。
new一个对象时会先检查在tlab缓冲区中有没有可用内存,有就优先在该区域进行分配。
对象分配也有线程安全问题,一段线程在分配某段内存时不能让别的线程也来用,会分配混乱。因此内存分配也要做并发安全保护(jvm实现)。
要减少线程在内存分配时的并发冲突就是用tlab,这样多个线程进行内存分配时也会有线程干扰。
正是因为大部分对选哪个用过即死才有Minor GC的时间远远低于FullGC
如何对新生代进行内存调优:
加大新生代内存????
上面参数用于设置新生代的初始和最大大小,设置太小导致执行大量小垃圾回收,设置太大,导致引发full GC,一次回收花费时间更多了。建议设置大于堆的四分之一,小于堆的二分之一 。
吞吐量 = 程序运行时间 / (程序运行时间 + 垃圾回收时间)
随着新生代空间变大,吞吐量会开始变小。因为后边垃圾回收时间也变大了。
总原则是将新生代空间调的尽可能大。
标记整理会产生很多碎片,整理的过程有很多需要判断碎片大小,移动垃圾位置。
原因之一:新生代垃圾的回收都是复制算法,分成标记和复制阶段,复制阶段花费时间更多,涉及内存块移动。 而新生代对象通常只有的少量对象可以存活。
理想内存
- 新生代能容纳所有[并发量*(请求+响应)] 的数据
- 幸存区大到能保留[当前活跃对象+需要晋升对象]
幸存区较小会由jvm动态调整晋升阈值,将对象提前晋升到老年代。
但是如果存活时间短的对象晋升到了老年代需要等到full GC才可以进行垃圾回收。
第一个是调整最大晋升阈值的参数
第二个是输出幸存区中的存活对象的年龄和占用空间的累计总和。
5.5 老年代调优
该参数是控制老年代在空间占用达到多少时进行CMS进行垃圾回收。
5.6 案例
第一个就是增加新生代内存
案例2
单次暂停时间长需要分析是那一部分的时间长,可以查看GC日志。
CMS的阶段如下,查看日志可以看见每一阶段耗费的时间。
cms在重新标记阶段使用了写屏障+增量复制算法来提高效率的。
重新标记阶段耗费1~2s的话是因为重新标记阶段要扫描整个堆内存,还要找引用。
在重新标记之前可以先对新生代做一次垃圾回收,减少垃圾数量,使用下面的参数开启该功能。
-XX:+CMSScavengeBeforeRemark
案例三
CMS有可能由于空间不足导致并发失败或者空间碎片过大都会引发full GC。
如果GC日志里面没有并发失败和碎片过多的错误提示说明老年代空间充裕。
jdk1.7用的永久代作为方法区实现,jdk1.8用的元空间。
元空间用的操作系统的容量一般比较充裕,不会有元空间空间不足。
1.7以前永久代空间设小了就会触发整个区的fullGC。
定位到是永久代空间不足导致fullGC,所以应该增大永久代空间。
相关文章:

JVM——垃圾回收器G1+垃圾回收调优
4.4 G1(一个垃圾回收器) 定义: 取代了CMS垃圾回收器。和CMS一样时并发的。 适用场景: 物理上分区,逻辑上分代。 相关JVM参数: -XX:UseG1GC-XX:G1HeapRegionSizesize-XX:MaxGCPauseMillistime 1) G1 垃圾回收阶段 三个回收阶段࿰…...
【SA8295P 源码分析】23 - QNX Ethernet MAC 驱动 之 emac1_config.conf 配置文件解析
【SA8295P 源码分析】23 - QNX Ethernet MAC 驱动 之 emac1_config.conf 配置文件解析 系列文章汇总见:《【SA8295P 源码分析】00 - 系列文章链接汇总》 本文链接:《【SA8295P 源码分析】23 - QNX Ethernet MAC 驱动 之 emac1_config.conf 配置文件解析》 主要参数如下: hw_…...

iptables的使用规则
环境中为了安全要限制swagger的访问,最简单的方式是通过iptables防火墙设置规则限制。 在测试服务器中设置访问swagger-ui.html显示如下,区分大小写: iptables设置限制访问9783端口的swagger字段的请求: iptables -A INPUT -p t…...
JS 动画 vs CSS 动画:究竟有何不同?
在 Web 前端开发中,动画是提高用户体验的关键因素之一。我们通常可以使用 JavaScript(JS)和 CSS 来创建动画效果。但是,这两者之间有哪些区别呢?在本文中,我们将深入研究 JS 动画和 CSS 动画,探…...

供应链 | 大数据报童模型:基于机器学习的实践见解
论文解读:李欣 马玺渊 作者:Gah-Yi Ban, Cynthia Rudin 引用:Ban, Gah-Yi and Cynthia Rudin. The big data newsvendor: Practical insights from machine learning. Operations Research 67.1 (2019): 90-108. 文章链接:https…...
Java开发工作问题整理与记录
1、为什么Autowired不能注入static成员属性 扫描Class类需要注入的元数据的时候,直接选择忽略掉了static成员(包括属性和方法) Spring 依赖注入是依赖set方法, set方法是普通的对象方法,static变量是类的属性 AutowiredAnnotationBeanPostP…...

静态代码扫描持续构建(Jenkins)
前提条件 已正确安装、配置Jenkins环境,并装有 Gradle 插件、HTML 插件、SVN 插件等。如下图所示: 已正确安装、配置android sdk,在cmd窗口输入命令“android -h”,回车 配置步骤 打开Jenkins,新建一个job,输入项目…...
Git gui教程---汇总篇
想说的 汇总篇就是你应该已经学会基本操作了。剩下的代码上传云端之类的我懒得教了,反正你看命令版也差不多了,具体怎么操作就自己想吧。接下来的汇总篇,主要将每一个篇章对应的git命令写出来,一一对应,毕竟现在的编辑…...

flink sql checkpoint 调优配置
- execution.checkpointing.interval: 检查点之间的时间间隔(以毫秒为单位)。在此间隔内,系统将生成新的检查点 SET execution.checkpointing.interval 6000; - execution.checkpointing.tolerable-failed-checkpoints: 允许的连续失败检查…...
Linux 网络文件共享介绍
Linux 网络文件共享介绍 一.常见的存储类型 目前常见的存储类型有 DAS,NAS,SAN 等,最主要的区别是硬盘存储媒介是如何 于处理器连接的,以及处理器使用何种方式来访问磁盘,以及访问磁盘使用 的协议(网络协议、I/O 协议)。 三种存储类型如下 直…...
Qt中如何在qml文件中使用其他的qml文件并创建对象
如果想使用其他的qml文件直接创建对象,必须先这样导入其qml文件并as成别名,才可以创建对象并使用它。 一、导入qml文件,例如: import "CameraConfig.qml" as CameraConfig import "CameraDevelopView.qml" a…...

学习心得04:CUDA
2018年的时候,看过同事使用CUDA。因为工作忙,所以也没请教。 近来买了本入门的CUDA书,学习了一番。有两个心得: 工作拆分。 CUDA是并行计算,也就是大量重复的可拆分的计算。数组最符合这个要求。简单点就是把数组外面…...
OpenCV实现摄像头图像分类(Python版)
先安装MMEdu库! MMEdu安装:https://blog.csdn.net/zyl_coder/article/details/132483865 下面的代码请在Jupyter上运行,并自己准备数据集。若模型还未训练,请先在本地训练完模型后再进行模型推理。 import cv2 capture cv2.Vi…...

计算机竞赛 地铁大数据客流分析系统 设计与实现
文章目录 1 前言1.1 实现目的 2 数据集2.2 数据集概况2.3 数据字段 3 实现效果3.1 地铁数据整体概况3.2 平均指标3.3 地铁2018年9月开通运营的线路3.4 客流量相关统计3.4.1 线路客流量排行3.4.2 站点客流量排行3.4.3 入站客流排行3.4.4 整体客流随时间变化趋势3.4.5 不同线路客…...
sonarqube报错http status 500-internal server error,什么原因,怎么解决
sonarqube报错http status 500-internal server error,什么原因,怎么解决 答案: SonarQube报错HTTP状态500-内部服务器错误通常是由于服务器端出现了一些问题导致的。这可能是由于配置错误、资源不足、数据库连接问题或其他一些未知的问题引起的。 以下…...
工业设计的四个主要阶段,你都知道吗?优漫动游
一般来说,工业设计有几个基本程序:概念过程——设计创造的意识,即为什么创造。如何使你的想法成为现实,最终形成一个实体;实现过程——在工作消费中创造;行为过程实现其所有价值。在整个设计过程中,设计师需要始终站在…...

【DevOps视频笔记】4.Build 阶段 - Maven安装配置
一、Build 阶段工具 二、Operate阶段工具 三、服务器中安装 四、修改网卡信息 五、安装 jdk 和 maven Stage1 : 安装 JDK Stage 2 : 安装 Maven 2-1 : 更换文件夹名称 2-2 : 替换配置文件 settings.xml- 2-3 : 修改settings.xml详情 A. 修改maven仓库地址 - 阿里云 B…...
linux非GUI模式执行带有jpgc线程组jmeter脚本报错
linux非GUI模式执行jmeter脚本报错 Error in NonGUIDriver java.lang.IllegalArgumentException: Problem loading XML from:/root/fer/xxx.jmx. Cause: CannotResolveClassException: kg.apc.jmeter.vizualizers.CorrectedResultCollectorDetail:com.thoughtworks.xstream.c…...

mysql处理json格式的字段,一文搞懂mysql解析json数据
文章目录 一、概述1、什么是JSON2、MySQL的JSON3、varchar、text、json类型字段的区别 二、JSON类型的创建1、建表指定2、修改字段 三、JSON类型的插入1、字符串直接插入2、JSON_ARRAY()函数插入数组3、JSON_OBJECT()函数插入对象4、JSON_ARRAYAGG()和JSON_OBJECTAGG()将查询结…...
测试数据生成
要生成300亿的文本数据,刚开始用python,实在是太慢了,改成c后速度提升了10几倍,看来干大事还是不能用python。代码留一下,以后可能还可以用上。 #include <stdio.h> #include <stdlib.h> #include <ti…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...

GraphQL 实战篇:Apollo Client 配置与缓存
GraphQL 实战篇:Apollo Client 配置与缓存 上一篇:GraphQL 入门篇:基础查询语法 依旧和上一篇的笔记一样,主实操,没啥过多的细节讲解,代码具体在: https://github.com/GoldenaArcher/graphql…...

第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10pip3.10) 一:前言二:安装编译依赖二:安装Python3.10三:安装PIP3.10四:安装Paddlepaddle基础框架4.1…...

C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...
React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构
React 实战项目:微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇!在前 29 篇文章中,我们从 React 的基础概念逐步深入到高级技巧,涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...