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,所以应该增大永久代空间。

 

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

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

相关文章

Pydev·离线git包

Pydev离线git包 1.下载离线git包:eclipse.egit.repository-4.4.0.201606070830-r.zip 2.将解压后目录:eclipse.egit.repository-4.4.0.201606070830-r\plugins下的jar文件放到 ide\eclipse\plugins目录下 3.重启pydevIDE 百度搜索站长工具:h…

不负众望~历时4年修炼,这本册子终于成书了(文末赠书)

名字:阿玥的小东东 学习:Python、C/C 主页链接:阿玥的小东东的博客_CSDN博客-python&&c高级知识,过年必备,C/C知识讲解领域博主 目录 精进Spring Boot首选读物 “小册”变“大书”,彻底弄懂Spring Boot 全方位配套资源…

PHP“牵手”淘宝商品评论数据采集方法,淘宝API接口申请指南

淘宝天猫商品评论数据接口 API 是开放平台提供的一种 API 接口,它可以帮助开发者获取商品的详细信息,包括商品的标题、描述、图片等信息。在电商平台的开发中,详情接口API是非常常用的 API,因此本文将详细介绍详情接口 API 的使用…

Linux journalctl命令详解(journalctl指令)(systemd服务默认日志管理工具)

文章目录 Linux Journalctl命令详解1. Journalctl简介2. Journalctl基础使用3. 过滤日志条目4. 时间戳和日志轮转5. 高级应用6. journalctl --help指令文档英文中文 注意事项journal日志不会将程序输出的空行显示,日志会被压缩得满满当当。journal日志不会自动持久化…

【C++入门到精通】C++入门 —— priority_queue(STL)优先队列

阅读导航 前言一、priority_queue简介1. 概念2. 特点 二、priority_queue使用1. 基本操作2. 底层结构 三、priority_queue模拟实现⭕ C代码⭕priority_queue中的仿函数 总结温馨提示 前言 ⭕文章绑定了VS平台下std::priority_queue的源码,大家可以下载了解一下&…

boost::array和boost::multi_array

boost::array Boost.Array是一个模板&#xff0c;需要两个模板参数&#xff0c;分别是数据的类型和数组的大小。 boost::array<int, 1024> temp_array;由于是模板参数&#xff0c;所以数组的大小必须是一个可以在编译阶段就可以推理得到的值。定义以后&#xff0c;就可…

数据结构——线性数据结构(数组,链表,栈,队列)

文章目录 1. 数组2. 链表2.1. 链表简介2.2. 链表分类2.2.1. 单链表2.2.2. 循环链表2.2.3. 双向链表2.2.4. 双向循环链表 2.3. 应用场景2.4. 数组 vs 链表 3. 栈3.1. 栈简介3.2. 栈的常见应用常见应用场景3.2.1. 实现浏览器的回退和前进功能3.2.2. 检查符号是否成对出现3.2.3. 反…

QT VS编译环境无法打开包括文件type_traits

这问题&#xff0c;别人给的处理方法都是&#xff1a; 添加环境变量执行vsvars32.bat/vcvarsall.bat/vsdevcmd.bat重新安装QT项目&#xff1a;执行qmake。。。。 个人不推荐配置环境编译&#xff0c;除非你非常熟&#xff0c;因为配置环境变量需要你知道有哪些路径需要添加&a…

手机自动无人直播,实景无人直播真的有用吗?

继数字人直播之后&#xff0c;手机自动直播开始火热了起来&#xff0c;因为其门槛低&#xff0c;成本低&#xff0c;一部手机一个账号就可以实现直播&#xff0c;一时深受广大商家的好评。那么&#xff0c;手机自动无人直播究竟是如何实现自动直播的呢&#xff1f; 在传统的直…

视频集中存储/云存储/磁盘阵列EasyCVR平台接入RTSP设备出现离线情况的排查

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

SAP LTMC基础教程之物料主数据详细操作示例

SAP LTMC基础教程之物料主数据详细操作示例 SAP S/4HANA 1610版本的推出已经不再建议使用LSMW了&#xff0c;使用中会受到很多限制&#xff08;比如特性、类的导入&#xff09;&#xff0c;而是推出了新工具LTMC。记录并分享LTMC的操作。 有几个注意点能够搞明白基本都能成功…

数据结构——B-树、B+树、B*树

一、B-树 1. B-树概念 B树是一种适合外查找的、平衡的多叉树。一棵m阶&#xff08;m>2&#xff09;的B树&#xff0c;是一棵平衡的M路平衡搜索树&#xff0c;它可以是空树或满足以下性质&#xff1a; &#xff08;1&#xff09;根节点至少有两个孩子。 &#xff08;2&#…

Qt关于hex转double,或者QByteArray转double

正常的00 ae 02 33这种类型的hex数据类型可以直接通过以下代码进行转换 double QDataConversion::hexToDouble(QByteArray p_buf) {double retValue 0;if(p_buf.size()>4){QString str1 byteArrayToHexStr(p_buf.mid(0,1));QString str2 byteArrayToHexStr(p_buf.mid(1,…

香蕉派社区推出带10G SFP+ 端口的Banana Pi BPI-R4 Wifi7开源路由器

香蕉派BPI-R4 根据著名Banana Pi品牌背后的公司Sinovoip提供的初步信息&#xff0c;他们即将推出的Banana Pi BPI-R4路由器板目前正在开发中。与之前的 Banana Pi R3 板相比&#xff0c;这在规格上将有显着提升。这就是我们目前所知道的。 您可以选择 R4 板的两种不同配置。具…

MySQL数据库的操作

目录 创建数据库字符集和校验规则查看系统默认字符集以及校验规则校验规则对数据库的影响 操纵数据库查看已经创建的数据库显示某个数据库的创建语句修改数据库删除数据库 数据库备份和还原备份还原 查看连接情况 创建数据库 语法: create database [if not exists] 数据库名字…

二、SQL,如何实现表的创建和查询

1、新建表格&#xff08;在当前数据库中新建一个表格&#xff09;&#xff1a; &#xff08;1&#xff09;基础语法&#xff1a; create table [表名]( [字段:列标签] [该列数据类型] comment [字段注释], [字段:列标签] [该列数据类型] comment [字段注释], ……&#xff0c…

java可变字符串

一、常用方法 以StringBuilder为例 1、append(String str) 添加 StringBuilder str new StringBuilder("hello"); System.out.println(str);//在源字符串后添加world StringBuilder add str.append("world"); System.out.println(add);//结果helloworl…

大数据时代,个人信息数据库保护的挑战及其对策

挑战&#xff1a; 数据泄露&#xff1a;大数据时代&#xff0c;个人信息数据库面临被黑客攻击、内部员工滥用权限等风险&#xff0c;导致个人信息泄露的风险增加。 隐私保护&#xff1a;随着大数据的快速发展&#xff0c;个人信息的采集和分析变得更加广泛和深入。但是&#xf…

kaggle注册不显示验证码

edge浏览器 1.点击浏览器右上角三个点 2.点击扩展 3.点击管理扩展 4.点击获取Microsoft Edge扩展&#xff0c;在左上角输入Head Editor 5.输入https://www.azurezeng.com/static/HE-GoogleRedirect.json 6.下载后&#xff0c;点保存 成功&#xff01;

天锐绿盾安全U盘系统

安全U盘系统 01 简介 天锐绿盾安全U盘系统&#xff0c;是一款致力于保障U盘数据内容安全的产品。通过严格身份认证、便捷安全的密保机制、智能的U盘锁定或自毁设置、详细的文件操作日志、文件粉碎、设置还原等&#xff0c;天锐绿盾安全U盘系统为您U盘的数据保驾护航&#xff0…