java语言的特点是自动化的垃圾回收机制
基于java中对象的特点:1,大部分对象的生命周期都很短;2,经历过多次回收而依旧存活的对象难以回收,3,方法区的对象很难回收。所以java的垃圾回收采用的思想是分代回收。
堆.png
上图中,新生代主要是minor gc 老年代主要是major gc ,full gc 针对整个堆空间和方法区
GC算法
复制算法
复制算法.png
将内存分为两部分,每次只使用一部分内存空间(A),进行垃圾回收时,将A中存活的对象复制到B并按照一定顺序放置,然后将A清理;优点:简单,不产生碎片;缺点:内存浪费。适用于新生代
appel式回收
这是java采用的垃圾回收算法,本质仍是复制算法,主要是将堆空间分为eden,s0,s1三部分,每次只使用eden+s区一部分,GC时复制到s区另一部分,默认比例8:1:1(这只是理论比例,实际情况由JVM动态计算),相对于复制算法,这种模式内存空间利用较高。
标记-清除
扫描内存空间两次,第一次扫描标记需要垃圾回收的对象,第二次清除被标记的对象。缺点是容易产生内存碎片,适用于老年代
标记-整理
扫描内存空间两次,除了标记需要垃圾回收的对象,还需要将存活对象进行整理,然后清除掉无用对象,优点是没有内存碎片,缺点是效率较低,适用于老年代
常用的垃圾回收器
常用垃圾回收器.png
图中展示了7种作用于不同分代的收集器,如果两个收集器之间存在连线,则说明它们可以搭配使用。虚拟机所处的区域则表示它是属于新生代还是老年代收集器。
新生代收集器:Serial、ParNew、Parallel Scavenge
老年代收集器:CMS、Serial Old、Parallel Old
整堆收集器: G1
几个相关概念:
STW(stop the world)单线程的垃圾回收器工作时,需要暂停所有的工作线程,造成应用短暂停止的现象。
并行收集指多条垃圾收集线程并行工作,但此时用户线程仍处于等待状态。
并发收集指用户线程与垃圾收集线程同时工作(不一定是并行的可能会交替执行)。用户程序在继续运行,而垃圾收集程序运行在另一个CPU上。
吞吐量即CPU用于运行用户代码的时间与CPU总消耗时间的比值(吞吐量 = 运行用户代码时间 / ( 运行用户代码时间 + 垃圾收集时间 ))。例如:虚拟机共运行100分钟,垃圾收集器花掉1分钟,那么吞吐量就是99%
Serial/Serial Old
特点:最早出现的垃圾回收器,单线程,独占式,适用于单CPU,一般客户端,现在基本抛弃
serial收集器工作流程.png
ParNew
多线程本版的Serial,基本和Serial类似,用于新生代的多线程的垃圾回收机制,一般和cms垃圾回收器配合适用
Parallel Scavenge
与吞吐量关系密切,故也称为吞吐量优先收集器。这也是很多服务端jvm默认的垃圾回收设计
特点:属于新生代收集器也是采用复制算法的收集器,又是并行的多线程收集器(与ParNew收集器类似)。
该收集器的目标是达到一个可控制的吞吐量。
GC自适应调节策略:Parallel Scavenge收集器可设置-XX:+UseAdptiveSizePolicy参数。当开关打开时不需要手动指定新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRation)、晋升老年代的对象年龄(-XX:PretenureSizeThreshold)等,虚拟机会根据系统的运行状况收集性能监控信息,动态设置这些参数以提供最优的停顿时间和最高的吞吐量,这种调节方式称为GC的自适应调节策略
Parallel Old
老年代版本的Parallel Scavenge,多线程,采用标记-整理算法。
CMS
以获取最短回收停顿时间为目标,减少STW,提高响应速度,老年代采用标记-清除算法(为了提高小效率所以没有采用标记-整理算法),易产生内存碎片,新生代配合ParNew
CMS收集器的运行过程分为下列4步:
初始标记:标记GC Roots能直接到的对象,速度快,耗时短,仍有STW。
并发标记:进行GC Roots 可达性分析,找出存活对象,耗时较长,所以与用户线程并发执行,。
重新标记:为了修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录;耗时短,会STW。
并发清除:对标记的对象进行清除回收。
CMS收集器的内存回收过程是与用户线程一起并发执行的。
cms.png
G1
设计思想G1 将堆内存“化整为零”,将堆内存划分成多个大小相等独立的Region,每一个Region
都可以根据需要,扮演新生代的Eden或Survivor ,或者老年代空间。回收器能够对扮演不同角色的Region 采用不同的策略去处理,这样无论是新创建的对象还是熬过多次收集的旧对象抑或是大对象都能获取很好的收集效果。
RegionG1中的Region除了可能是Eden,Survivor,Old之外,还有一个Humongous 区域,专门用来存储大对象。G1 的进行回收大多数情况下都把Humongous Region 作为老年代的一部分来进行处理。
相对于前面的垃圾回收器,其主要特点是:1,采用了分区思想(region);2,由于分区,可以预测STW的时间,可以尽可能的减少STW的时间,提高用户体验。
忽略一些算法问题,大致可以将G1分成以下几步:
初始标记:标记GC Root直接引用的对象,耗时短,STW
并发标记:从GC Root进行可达性分析,耗时长,但是可以与用户线程并行
最终标记:处理并发标记中漏标的对象,STW
筛选回收:依据目标选择若干个region进行回收,STW
G1流程.png