Java垃圾回收(4)

G1:垃圾优先

G1收集器是热点JVM中要实现的最新收集器。 自Java 7 Update 4以来,它一直是受支持的收集器。OracleGC团队也公开表示,他们对低暂停GC的希望是完全实现的G1。 这篇文章来自我之前的垃圾收集博客文章:

  1. 热点GC概述 。
  2. 并行垃圾收集器 。
  3. 并发标记扫描 。

问题:大堆意味着长暂停时间

并发标记和扫描(CMS)收集器是当前推荐的低暂停收集器,但是不幸的是,其暂停时间随使用权区域中活动对象的数量而定。 这意味着,尽管使用较小的堆获得较短的GC暂停相对容易,但是一旦开始使用10或100千兆字节的堆,时间就会开始增加。

CMS也不会“整理”其堆,因此在某个时间点您会遇到并发模式故障(CMF),从而触发完整的gc。 一旦进入了完整的gc场景,您就可以预期每千兆字节活动对象大约1秒钟的时间间隔。 使用CMS,您的100GB堆可能是等待1.5分钟的GC暂停滴答定时炸弹……

复制品_m67_hand_grenade_wip_by_danboldy-d4ewsgk

良好的GC调优可以解决此问题,但有时只会将问题推向前进。 并发模式失败和完整GC不可避免地会在足够长的时间范围内出现,除非您处在一小部分专门避免填充其使用期限的人员中。

G1堆布局

G1收集器试图通过将堆分成不同的区域来将单个集合的暂停时间与堆的整体大小分开。 每个区域的大小都是固定的,介于1MB和32MB之间,JVM的目标是总共创建大约2000个区域。

g1地区

您可能还记得以前的文章,其他收集器将堆分为Eden,Survior Space和Tenured内存池。 G1保留相同类别的池,但不是将它们作为连续的内存块,而是将每个区域在逻辑上分类为这些池之一。

还有另一种类型的区域-大型区域。 这些对象用于存储大小比大多数对象大的对象,例如,很长的数组。 任何大于区域大小50%的对象都存储在巨大的区域中。 它们通过获取连续位于内存中的多个普通区域并将它们视为单个逻辑区域来工作。

g1区域类型

记忆集

当然,如果您将不得不扫描整个堆以找出哪些对象被标记为活动对象,那么将堆分成多个区域毫无意义。 实现此目标的第一步是将区域分成称为卡的512字节段。 每张卡在卡标记表中都有一个1字节的条目。

每个区域都有一个关联的记忆集或RSet-这是已写入的卡集。 如果卡片中存储的另一个区域中的某个对象指向该区域中的某个对象,则卡片在记忆集中。

每当更改器写入对象引用时,就会使用写屏障来更新所记住的集合。 在幕后,记住的集合被分为不同的集合,以便不同的线程可以在没有争用的情况下运行,但是从概念上讲,所有集合都是同一集合的一部分。

并发标记

为了标识哪些堆对象是活动的,G1执行活动对象的大部分并发标记。

  • 标记阶段标记阶段的目标是弄清楚堆中哪些对象是活动的。 为了存储哪些对象处于活动状态,G1使用了标记位图-堆中每64位存储一个位。 从所有对象的根部开始跟踪,并在标记位图中使用活动对象标记区域。 这通常是并发的,但是有一个类似于CMS的“ 初始标记暂停” ,其中应用程序被暂停并且跟踪根对象的第一级子级。 完成此步骤后,重新启动线程。 G1需要保持对堆中生活内容的最新了解,因为不会在标记阶段的同一暂停中清理堆。
  • 标记阶段标记阶段的目标是使标记阶段中有关活动对象的信息保持最新。 首先要做的是确定何时进行标记。 由一定百分比的堆已满触发。 这是通过从标记阶段和此后的分配数量中获取信息来计算的,并告诉G1其是否超过了要求的百分比。 G1使用前面提到的写屏障来记录对堆的更改,并将其存储在一系列更改缓冲区中 。 更改缓冲区中的对象同时在标记位图中标记。 当达到填充百分比时,将再次暂停更改程序线程并处理更改缓冲区,从而将更改缓冲区中的对象标记为活动状态。
  • 清理阶段此时,G1知道哪些对象处于活动状态。 由于G1专注于可用空间最大的区域,因此下一步是通过对活动对象进行计数来计算给定区域中的可用空间。 这是从标记位图计算得出的,并且根据最有可能收集到哪些区域来对区域进行排序。 要收集的区域存储在所谓的收集集或CSet中

疏散

与半球年轻一代在并行GC和CMS收集器中采用的方法类似,不会收集死物。 取而代之的是,将有生命的物体从某个区域撤离,然后将整个区域视为空闲区域。

G1对于如何回收活动物体很聪明–它不会尝试在给定的周期内回收所有活动物体。 它针对的是可能会回收尽可能多空间的区域,仅将其撤离。 它通过计算活动对象在一个区域内的比例并选择活动对象比例最低的区域来确定其目标区域。

将物体从多个其他区域撤离到自由区域。 这意味着G1在执行GC时会压缩数据。 这由多个线程并行操作。 传统的“平行GC”可以做到这一点,而CMS不这样做。

与CMS和Parallel GC相似,存在终身制的概念。 也就是说,如果年轻对象在足够的收藏中存活下来,它们就会变“旧”。 此数字称为任职期限。 如果年轻的世代区域在任职期限内幸免,并保留了足够的活物以避免被疏散,则该区域将得到提升。 首先是幸存者,最后是终身制地区。 它从未被疏散。

疏散失败

不幸的是,G1仍然会遇到类似于并发模式故障的情况,在这种情况下,它会退回到Stop the World Full GC。 这称为疏散失败,在没有空闲区域时发生。 没有自由区域意味着没有地方疏散物体。

理论上,与CMS中的并发模式故障相比,G1中发生疏散失败的可能性较小。 这是因为G1会即时压缩其区域,而不仅仅是等待压缩失败。

结论

尽管进行了压缩和在低暂停时做出的努力,但G1并不能保证一定会获胜,采用它的任何尝试都应伴随有客观且可衡量的性能目标以及GC Log分析。 所需的方法超出了本博客文章的范围,但希望我会在以后的文章中介绍它。

从算法上讲,G1会遇到其他Hotspot收集器不会遇到的开销。 值得注意的是,维护记忆集的成本。 并行GC仍然是推荐的吞吐量收集器,并且在许多情况下CMS都比G1更好。

现在说G1是否会比CMS收集器大胜还为时过早,但是在某些情况下,它已经为使用它的开发人员提供了好处。 随着时间的流逝,我们将看到G1的性能限制是否真的是G1的限制,或者开发团队是否仅需要更多的工程工作来解决那里的问题。

感谢John Oliver , Tim Monks和Martijn Verburg审阅了本期及以前的GC文章的草稿。

参考: Insightful Logic博客上来自我们JCG合作伙伴 Richard Warburton的Java垃圾收集(4) 。

翻译自: https://www.javacodegeeks.com/2013/07/garbage-collection-in-java-4.html

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

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

相关文章

Html5 冒泡排序演示

本文通过一个简单的小例子,简述冒泡算法在B/S中的简单使用,仅供学习分享使用,如有不足之处,还请指正。 概述 冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。 它重复地走访…

一种编写测试的好方法

测试。 最近我一直在考虑进行测试。 作为我对各种项目所做的代码审查的一部分,我已经看到了数千行未经测试的代码。 这不仅是测试覆盖率统计数据指出这一点的情况,还更多是该项目中根本没有任何测试的情况 。 我一直听到这种悲惨状况的两个原因&#xff…

rem、px、em之间的区别以及网页响应式设计写法

个人收藏用,转载自:http://www.w3cplus.com/css3/define-font-size-with-css3-rem 在Web中使用什么单位来定义页面的字体大小,至今天为止都还在激烈的争论着,有人说PX做为单位好,有人说EM优点多,还有人在说…

游戏服务器架构图

1:ARPG类型游戏 2:MMORPG 3:MOBA 4:卡牌类 5:棋盘类 转载于:https://www.cnblogs.com/like-minded/p/8297718.html

GlassFish 4带来了Java EE 7

真是惊喜 除了推出新的iOS 7外,苹果在wwdc上什么也没提供。 碰巧的是,在他们的主题演讲后不久,又有7个人正式露面。 GlassFish 4.0已于昨天晚上发布(显然是不需要的)。 新的Java EE 7参考实现自动成为当今第一个可用的…

bootstrap的栅格布局与两列布局结合使用

在工作中我们常常需要实现响应式布局,这个可以使用bootstrap的栅格系统来实现,我们在列里也需要实现一部分的响应式。比如下面的效果图,需要实现左边图标固定,右边的自适应 : 左边固定宽度,右边自适应&…

JVM性能魔术技巧

HotSpot是我们众所周知和喜爱的JVM,是Java和Scala汁流淌的大脑。 多年来,许多工程师对其进行了改进和调整,并且在每次迭代中,其代码执行的速度和效率都接近本机编译代码。 JIT(“即时”)编译器是其核心。…

mysql 10个日期,MySQL自学篇(10)——日期函数

MySQL自学篇(十)——日期函数日期和时间函数(1)获取当前日期的函数和时间的函数CURDATE()和CURRENT_DATE()函数,获取当前日期select current_date(),curdate(),curdate()0;curdate()0 表示将当前时间转化为数值型CURTIME()和CURRENT_TIME()获取当前时间select cur…

python-flask-请求源码流程

启动先执行manage.py 中的 app.run() class Flask(_PackageBoundObject):   def run(self, hostNone, portNone, debugNone, **options):from werkzeug.serving import run_simpletry:#run_simple 是werkzeug 提供的方法,会执行第三个参数 self()run_simple(ho…

正则表达式强化,爬虫练习

re模块下的常用方法 import re ret re.findall(\d(\.\d)?, 1.232.34)   print(ret) 结果: [.23,.34] # findall的正则表达式里面有分组(),()里面的内容优先显示 ret re.findall(\d(?:\.\d)?, 1.232.34)print(ret)    结果:…

Linux LVM管理

LVM(Logical Volume Manager)逻辑卷管理是在Linux2.4内核以上实现的磁盘管理技术。它是Linux环境下对磁盘分区进行管理的一种机制。 本文内容: 创建和管理LVM扩容LVM分区一、创建和管理LVM 要创建一个LVM系统,一般需要经过以下步骤: 1、 创建…

USB OTG插入检测识别

一 USB引脚一般四根线,定义如下: 为支持OTG功能,mini/micro usb接口扩展了一个ID引脚(第4脚) A设备端ID脚接地,则初始状态为Host,例如PC和支持OTG设备做主设备时 B设备端ID脚悬空,默…

CSS3与页面布局学习笔记(三)——BFC、定位、浮动、7种垂直居中方法

一、BFC与IFC 1.1、BFC与IFC概要 BFC(Block Formatting Context)即“块级格式化上下文”, IFC(Inline Formatting Context)即行内格式化上下文。常规流(也称标准流、普通流)是一个文档在被显示…

Java垃圾回收(2)

并行清理 今天,我们介绍了并行GC的工作原理。 具体来说,这是在Eden上运行Parallel Scavenge收集器,在Tenured一代中运行Parallel Mark and Sweep收集器的组合。 您可以通过传递-XX: UseParallelOldGC来获得此选项,尽管…

Navicat Premium创建MySQL存储过程

1、使用Navicat Premium打开创建函数向导,操作:连接名——数据库——函数——新建函数 2、选择过程——输入存储过程参数——完成(这一步可以不填写参数,编写存储过程代码的时候设置参数) 3、按照要求完成存储过程代码…

CSS3与页面布局学习笔记(二)——盒子模型(Box Model)、边距折叠、内联与块标签、CSSReset

一、盒子模型(Box Model) 盒子模型也有人称为框模型,HTML中的多数元素都会在浏览器中生成一个矩形的区域,每个区域包含四个组成部分,从外向内依次是:外边距(Margin)、边框&#xff…

mysql中将某个字段做计算,mysql创建计算字段使用子查询教程

作为计算字段使用子查询使用子查询的另一方法是创建计算字段。假如需要显示 customers表中每个客户的订单总数。订单与相应的客户ID存储在 orders 表中。为了执行这个操作,遵循下面的步骤。(1) 从 customers 表中检索客户列表。(2) 对于检索出的每个客户&#xff0c…

Android GreenDao使用教程

一、Greendao简介 Greendao是一款用于数据库创建与管理的框架,由于原生SQLite语言比较复杂繁琐,使得不少程序员不得不去学习SQLite原生语言,但是学习成本高,效率低下,所以不少公司致力于开发一款简单的数据库管理框架&…

Java垃圾回收(1)

这是有关垃圾收集(GC)的系列文章中的第一篇。 我希望能够涵盖整个系列过程中的理论知识以及热点虚拟机中的所有主要收集器。 这篇文章仅说明什么是垃圾回收,以及不同回收器共有的元素。 我为什么要在乎? 您的Java虚拟机可以为您管…

少锁定Java对象池

自从我写任何东西以来已经有一段时间了,我一直在忙于我的新工作,该工作涉及在性能调整方面做一些有趣的工作。 挑战之一是减少应用程序关键部分的对象创建。 尽管Java随着时间的推移改进了GC算法,但垃圾回收打h一直是Java的主要难题。 Azul是…