G1垃圾收集器架构和如何做到可预测的停顿(阿⾥)
CMS垃圾回收机制参考:
CMS与G1的区别参考:
写这篇⽂章是基于阿⾥⾯试官的⼀个问题:众所周期,G1跟其他的垃圾回收算法差别很⼤,你了解G1的垃圾回收架构吗?为什么G1可以做到回收时间⽤户可以设定?
G1垃圾回收器其实是JDK7的特性,在⽬前JDK10都已经发布的情况下,已经不是什么新特性了,⽽我到它现在才关注它,可见我是有多么的懒;⽽我终于关注它了,可见我的懒还算是有救的 :)
G1其实是Garbage First的意思,垃圾优先? 不是,是优先处理那些垃圾多的内存块的意思。在⼤的理念上,它还是遵循JVM的内存分代假设(其实叫假设不准确,这是从实际Java应⽤的内存使⽤观察得到的结论):
90%的对象熬不过第⼀次垃圾回收,⽽⽼的对象(经历了好⼏次垃圾回收的对象)则有98%的概率会⼀直活下来。
基于这个分代假设,⼀般的垃圾回收器把内存分成三类: Eden(E), Suvivor(S)和Old(O), 其中Eden和Surviv
or都属于年轻代,Old属于⽼年代,新对象始终分配在Eden⾥⾯,熬过⼀次垃圾回收的对象就被移动到Survisor区了,经过数次垃圾回收之后还活着的对象会被移到Old 区。
⼀般GC的内存分布
这样分代的好处是,把⼀个复杂的⼤问题,分成两类不同的⼩问题,针对不同的⼩问题,采⽤更有针对性的措施(分⽽治之):
对于年轻代的对象,由于对象来的快去得快,垃圾收集会⽐较频繁,因此执⾏时间⼀定要短,效率要⾼,因此要采⽤执⾏时间短,执⾏时间的长短只取决于对象个数的垃圾回收算法。但是这类回收器往往会⽐较浪费内存,⽐如Copying GC,会浪费⼀半的内存,以空间换取了时间。
对于⽼年代的对象,由于本⾝对象的个数不多,垃圾收集的次数不多,因此可以采⽤对内存使⽤⽐较⾼效的算法。
跟其它垃圾回收器不⼀样的是:G1虽然也把内存分成了这三⼤类,但是在G1⾥⾯这三⼤类不是泾渭分明的三⼤块内存,G1把内存划分成很多⼩块, 每个⼩块会被标记为E/S/O中的⼀个,可以前⾯⼀个是Eden后⾯⼀个就变成Survivor了。
G1的内存分布
这么做给G1带来了很⼤的好处,由于把三块内存变成了⼏百块内存,内存块的粒度变⼩了,从⽽可以垃圾回收⼯作更彻底的并⾏化。java做什么的
G1的并⾏收集做得特别好,我们第⼀次听到并⾏收集应该是CMS(Concurrent Mark & Sweep)垃圾回收算法, 但是CMS的并⾏收集也只是在收集⽼年代能够起效,⽽在回收年轻代的时候CMS是要暂停整个应⽤的(Stop-the-world)。⽽G1整个收集全程⼏乎都是并⾏的,它回收的⼤致过程是这样的:
在垃圾回收的最开始有⼀个短暂的时间段(Inital Mark)会停⽌应⽤(stop-the-world)
然后应⽤继续运⾏,同时G1开始Concurrent Mark
再次停⽌应⽤,来⼀个Final Mark (stop-the-world)
最后根据Garbage First的原则,选择⼀些内存块进⾏回收。(stop-the-world)
由于它⾼度的并⾏化,因此它在应⽤停⽌时间(Stop-the-world)这个指标上⽐其它的GC算法都要好。
G1的另⼀个显著特点他能够让⽤户设置应⽤的暂停时间,为什么G1能做到这⼀点呢?也许你已经注意到了,G1回收的第4步,它是“选择⼀些内存块”,⽽不是整代内存来回收,这是G1跟其它GC⾮常不同的⼀点,其它GC每次回收都会回收整个Generation的内存(Eden, Old), ⽽回收内存所需的时间就取决于内
存的⼤⼩,以及实际垃圾的多少,所以垃圾回收时间是不可控的;⽽G1每次并不会回收整代内存,到底回收多少内存就看⽤户配置的暂停时间,配置的时间短就少回收点,配置的时间长就多回收点,伸缩⾃如。 (阿⾥⾯试)
由于内存被分成了很多⼩块,⼜带来了另外好处,由于内存块⽐较⼩,进⾏内存压缩整理的代价都⽐较⼩,相⽐其它GC算法,可以有效的规避内存碎⽚的问题。
说了G1的这么多好处,也该说说G1的坏处了,如果应⽤的内存⾮常吃紧,对内存进⾏部分回收根本不够,始终要进⾏整个Heap的回收,那么G1要做的⼯作量就⼀点也不会⽐其它垃圾回收器少,⽽且因为本⾝算法复杂了⼀点,可能⽐其它回收器还要差。因此G1⽐较适合内存稍⼤⼀点的应⽤(⼀般来说⾄少4G以上),⼩内存的应⽤还是⽤传统的垃圾回收器⽐如CMS⽐较合适。
总结
G1通过在垃圾回收领域应⽤并⾏化的策略,把⼏块⼤内存块的回收问题,变成了⼏百块⼩内存的回收问题,使得回收算法可以⾼度并⾏化,同时也因为分成很多⼩块,使得垃圾回收的单位变成了⼩块内存,⽽不是整代内存,使得⽤户可能对回收时间进⾏配置,垃圾回收变得可以预期了。
分⽽治之、化整为零这些朴素的架构思想往往是很多⽜叉技术产品背后的思想根源啊。
参考:
总结这篇⽂章和其他的资料,G1可以基本稳定在0.5s到1s左右的延迟,但是并不能保证更低的⽐如毫秒级(⾦融场景,所以说涉及到钱的,对技术要求真⾼),号称zing可以(但是⼀般做到低延时,在其他⽅⾯肯定有所损耗,⽐如吞吐),但是没有实际去研究过这种。另外,G1也可能和CMS⼀样出现Full GC,如果区域不够提升的话,所以它⼀般⽤于需求更⼤的堆中。但G1最显著于CMS的,在于它对空间做了整理,这样减少了空间的碎⽚化。CMS的空间碎⽚话相较于G1要严重很多,试想下它的Mark-Sweep之后的空间,有很多⼩碎⽚,但是都⽐要分配的⼩,然后触发⼀次Full GC,简直了。再说点杂的,G1的思想,感觉有点像Java CocurrentHashMap,也是将⼀个⼤的分成若⼲个Region,然后再处理
G1 垃圾收集器⼊门
概览
⽬的
这个教程覆盖了如何使⽤G1垃圾收集器和它是怎样被Hotspot JVM使⽤的,你会学到G1收集器内部是如何⼯作的,使⽤G1时的⼀些关键命令⾏开关和记录它的操作的⼀些选项。
完成耗时
⼤约1⼩时
介绍
这个OBE(Oracle By Example)覆盖了Java⾥的Java虚拟机G1垃圾回收的基本概念,在OBE的第⼀部分,
在介绍垃圾收集器和性能时会附带提供JVM的概览。下⼀部分回顾⼀下Hotspot JVM的CMS收集器如何⼯作。然后,⼀步⼀步来指导使⽤Hotspot JVM的G1垃圾回收,跟着,会⽤⼀段来讲G1垃圾回收器的可⽤的命令⾏选项。最后,你会学到G1回收器的⽇志选项。
硬件、软件需求
下⾯是⼀个硬件软件需求列表:
⼀台运⾏Windows XP或者更⾼版本的PC,Mac OS X或者Linux。注意已在Windows 7系统亲测,还没有在所有平台测试。然⽽,应该会在OS X或Linux上正常运⾏。多处理器核⼼的机器更好。
Java 7 Update 9或更⾼版本
最新Java 7 演⽰和⽰例压缩⽂件
先决条件
开启教程之前,你应该:
如果你没有这样做,下载安装最新版本的JDK,。
从同样的地址下载安装演⽰⽰例压缩⽂件,解压⽂件到⼀个⽬录中,⽐如:C:/javademos
Java技术和虚拟机
Java概览
Java是Sun微系统公司在1995年⾸次发布的⼀个编程语⾔和计算平台。它是⽀撑Java程序包括⼯具、游戏、商业应⽤的底层技术。在全球Java运⾏在超过8亿5千万台个⼈电脑上,数以⼗亿计的设备上,包括移动、电视设备。Java由⼀些关键组件组成,作为⼀个整体,创建Java平台。
Java运⾏时
当你下载Java,你获得Java运⾏环境(JRE,Java Runtime Environment)。 JRE由Java虚拟机(JVM)
、Java平台核⼼类和⽀撑Java平台的库组成。要在你电脑上运⾏Java应⽤,所有的这些都是必须的。有了Java 7, Java应⽤从操作系统⽅⾯来说是作为桌⾯应⽤运⾏的,作为⼀个桌⾯应⽤但是从⽹络上安装需要使⽤Java Web Start,或者在浏览器⾥作为⼀个Web嵌⼊式的应⽤(使⽤JavaFX)
Java编程语⾔
Java是⼀个⾯向对象的编程语⾔,包含以下特性:
平台独⽴ - Java应⽤被编译成存储在类⽂件中的字节码,在JVM⾥被加载。⼀旦应⽤在JVM⾥运⾏,它们可以运⾏在许多不同的操作系
统和设备上。
⾯向对象 - Java是⼀个⾯向对象的语⾔,借鉴了C和C++的诸多特性,在它们之上改进。
⾃动垃圾收集 - Java⾃动分配和释放内存,所以程序不必背负这个任务。
丰富的标准库 - Java包括⼤量预先做好的对象,它⽤被⽤在执⾏⽐如输⼊/输出、⽹络、数据操作这样的任务上。
Java开发⼯具箱
Java开发⼯具箱(JDK,Java Development Kit)是⼀个开发Java应⽤的⼯具集。有了JDK,你可以编译⽤Java语⾔编写的应⽤程序,在JVM⾥⾯运⾏它们。另外,JDK提供⼯具打包和发布你的应⽤。
JDK和JRE分享同样的Java应⽤编程接⼝(Java API,Java Application Programming Interfaces)。Java API是已经打包的库的集合,开发者⽤来创建Java应⽤。Java API通过提供⼯具完成很多通常的编程任务包括字符串操作、时间⽇期处理、⽹络和实现数据结构(⽐如:列表、映射、栈和队列)使开发更加容易。
Java虚拟机
Java虚拟机(JVM,Java Virtual Machine)是⼀个抽象的计算机器,Java虚拟机是⼀个程序,对在它⾥⾯运⾏的编写的程序来说,看起来像⼀个机器。这样,Java程序就会⽤相同的接⼝和库来编写。每⼀个针对特定操作系统的JVM实现,把Java程序指令翻译成运⾏在本地操作系统的指令和命令。这样,Java程序实同了平台独⽴。
Sun微系统公司完成了第⼀个Java虚拟机的原型实现,仿真Java虚拟机指令集设置进⼀个被类似当时的个⼈数码助⼿(PDA,Personal Digital Assistant)⼿持设备的托管的软件⾥。Oracle现在实现仿真Java虚拟机在移动、桌⾯和服务器设备上,但是Java虚拟机没有承担任何具体的技术实现,管理硬件或者管理操作系统。It is not inherently interpreted, but can just as well be implemented by compiling its instru
ction set to that of a silicon CPU. It may also be implemented in microcode or directly in silicon(斜体这⾥翻译不清楚,请⼤神指点。好像涉及解释执⾏、指令集、微码等)
Java虚拟机对Java编程语⾔⼀概不知,只知道⼀个特定的⼆进制格式,就是类⽂件格式,⼀个类⽂件包含Java虚拟机指令(或者叫字节码)和⼀个符号表,和⼀些辅助信息。
为了达到安全的⽬的,Java虚拟机在类⽂件代码上利⽤强⼤的语法和结构化的约束条件。然⽽任何函数性语⾔可以依照⼀个可⽤的被Java虚拟机托管类⽂件来表达。被通⽤的、机器平台独⽴性吸引,其它语⾔的实现者可以把Java虚拟机视为其它语⾔的递送载体,
探索Java虚拟机架构
Hotspot架构
Hotspot虚拟机拥有⼀个架构,它⽀持强⼤特性和能⼒的基础平台,⽀持实现⾼性能和强⼤的可伸缩性的能⼒。举个例⼦,Hotspot虚拟机JIT 编译器⽣成动态的优化,换句话说,它们在Java应⽤执⾏期做出优化,为底层系统架构⽣成⾼性能的本地机器指令。另外,经过它的运⾏时环境和多线程垃圾回收成熟的进化和连续的设计,Hotspot虚拟机在⾼可⽤计算系统上产出了⾼伸缩性。
Java虚拟机的主要组件,包括类加载器、运⾏时数据区和执⾏引擎。Hotspot关键组件
Java虚拟机有关性能的关键组件已经在下⾯的图⽚上⾼亮显⽰了。
Java虚拟机有三个组件关注着什么时候进⾏性能优化,堆空间是你的对象所存储的地⽅,这个区域
被启动时选择的垃圾回收器管理,⼤部分调优选项与调整堆⼤⼩和根据你的情况选择最适当的垃圾收集器相关。即时编译器对性能也有很⼤的影响,但是使⽤新版本的Java虚拟机时很少需要调整。
性能基础
典型的,当调优⼀个Java应⽤时,把焦点放在两个主要的⽬标上:响应能⼒或者吞吐量。随着教程的进⾏我们会再重新提及这些概念。
响应能⼒
响应能⼒指的是⼀个应⽤回应⼀个请求数据的速度有多快。⽰例包括:
桌⾯UI响应事件的速度
⽹站返回⽹页的速度
数据查询返回的速度
对关注响应能⼒的应⽤来说,长暂停时间是不可接受的,重点是在短的时间周期内能做出响应。
吞吐量
吞吐量关注在特定的时间周期内⼀个应⽤的⼯作量的最⼤值。举例如何衡量吞吐量,包括:
给定时间内完成事务的数量
⼀⼩时内批处理程序完成的⼯作数量
⼀⼩时内数据查询完成的数量
对关注吞吐量的应⽤来说长暂停时间是可以接受的。由于⾼吞吐量的应⽤关注的基准在更长周期时间上,所以快速响应时间不在考虑之内。
G1垃圾回收器
G1垃圾回收器
Garbage-First(G1,垃圾优先)收集器是服务类型的收集器,⽬标是多处理器机器、⼤内存机器。它⾼度符合垃圾收集暂停时间的⽬标,
同时实现⾼吞吐量。Oracle JDK 7 update 4 以及更新发布版完全⽀持G1垃圾收集器。G1垃圾回集器为
以下应⽤设计:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。