赞
踩
按线程数分, 可以分为串行回收器和并行回收器
按工作模式分, 可以分为并发式垃圾回收器和独占式垃圾回收器
按碎片处理方式分, 可以分为压缩式垃圾回收器和非压缩式垃圾回收器
按工作的内存区间分, 又可分为年轻代垃圾回收器和老年代垃圾回收器
高吞吐量较好因为这会让应用程序的最终用户感觉只有应用程序线程在做"生产性"工作. 直觉上, 吞吐量越高程序运行越快
低暂停时间(低延迟)较好因为从最终用户的角度来看不管时GC还是其他原因导致一个应用被挂起始终是不好的. 因此, 具有低的较大暂停时间是非常重要的, 特别是对于一个交互式应用程序
不幸的是. "高吞吐量"和"低暂停时间"是一对相互竞争的目标.
如果选择以吞吐量优先, 那么必然需要降低内存回收的执行频率, 但这样会导致GC需要更长的暂停时间来执行内存回收.
如果选择以低延迟优先为原则, 那么为了降低每次执行内存回收的暂停时间, 只能频繁地执行内存回收, 但这又引起了来来取代内存的缩减和导致程序吞吐量的下降.
现在标准: 在最大吞吐量优先的情况下, 降低停顿时间
串行回收器
Serial, Serial Old
并行回收器
ParNew, Parallel Scavenge, Parallel Old
并发回收器
CMS, G1
收集器与垃圾分代之间的关系
垃圾收集器的组合关系
Serial收集器是最基本, 历史最悠久的垃圾收集器了. JDK1.3之前收集新生代唯一的选择
Serial收集器作为HotSpot中Client默认下的默认新生代垃圾收集器
Serial收集器采用复制算法, 串行回收和"Stop-the-world"机制的方式执行内存回收.
除了年轻代之外, Serial收集器还提供用于执行老年代垃圾收集器的Serial Old收集器. Serial Old收集器同样也采用了串行回收和"Stop the World"机制, 只不过内存回收算法使用的是标记-压缩算法.
Serial Old是运行在Client模式下默认的老年代的垃圾回收器
Serial Old在Server模式下主要有两个用途:
① 与新生代的Parallel Scavenge配合使用
② 作为老奶奶带CMS收集器的后备垃圾收集方案
这个收集器是一个单线程的收集器, 但它的"单线程"的意义并不仅仅说明它只会使用一个CPU或一条收集线程区完成垃圾收集工作, 更重要的是它进行垃圾收集时, 必须暂停其他所有的工作线程, 直到它收集结束(Stop the World)
优势: 与其他收集器的单线程比, 简单而高效
运行在Client模式下的虚拟机时个不错的选择
在HotSpot虚拟机中, 使用-XX:+UseSerialGC
参数可以指定年轻代和老年代都是用串行收集器
等价于: 新生代用Serial GC, 且老年代用 Serial Old GC
如果Serial GC是年轻代中的单线程垃圾收集器, 那么ParNew收集器则是Serial收集器的多线程版本
ParNew收集器除了采用并行回收的方式执行内存回收外, 两款垃圾收集器之间机会没有任何区别. ParNew收集器在年轻代中同样也是采用复制算法, "Stop-the-World"机制
ParNew 是很多JVM运行在Server模式下新生代的默认垃圾收集器
对于新生代, 回收次数频繁, 使用并行方式高效
对于老年代, 回收次数少, 使用串行方式节省资源
由于ParNew收集器是基于并行回收, 那么是否可以断定ParNew收集器的回收效率在任何场景下都会比Serial收集器更高效?
除Serial外, 目前只有ParNew GC能与CMS收集器配合工作
在程序中, 开发人员可以通过选项-XX:+UseParNewGC
手动指定使用ParNew收集器执行内存回收任务. 它表示年轻代使用并行收集器, 不影响老年代
-XX:ParallelGCThreads
限制线程数量, 默认开启和CPU数据相同的线程数
HotSpot的年轻代中除了拥有ParNew收集器是基于并行回收的以外, Parallel Scavenge收集器同样也采用了复制算法, 并行回收 和 "Stop the World"机制
和ParNew收集器不同, Parallel Scavenge收集器的目标是达到一个可控制的吞吐量(Throughput), 它也被称为吞吐量优先的垃圾收集器
自适应调节策略也是Parallel Scavenge与ParNew一个重要区别
高吞吐量则可以高效率地利用CPU时间, 尽快完成程序的运算任务, 主要适合在后台运算而不需要太多交互的任务. 因此, 常见在服务器环境中使用
Parallel收集器在JDK1.6时提供了用于执行老年代垃圾收集的Parallel Old收集器, 用来代替老年代Serial Old收集器
Parallel Old收集器采用了标记-压缩算法, 但同样也是基于并行回收和"Stop-the-World"机制
在程序吞吐量优先的应用场景中, Parallel收集器和Parallel Old收集器的组合, 在Server模式下的内存回收性能很不错
在JDK8中, 默认时此垃圾收集器
-XX:+UseParallelGC
: 手动指定年轻代使用Parallel并行收集器执行内存回收任务-XX:+UseParallelOldGC
: 手动指定老年代都是使用并行收集器.
-XX:ParallelGCThreads
: 设置年轻代并行收集器的线程数. 一般地, 最好与CPU数量相等, 以避免过多的线程数影响垃圾收集性能-XX:MaxGCPauseMillis
: 设置垃圾收集器最大停顿时间(即STW的时间), 单位是毫秒
-XX:GCTimeRatio
: 垃圾收集十进占总时间的比例(= 1 / (N + 1)), 用于衡量吞吐量的大小
-XX:MaxGCPauseMillis
参数有一定矛盾性. 暂停时间越长, Ratio参数就越容易超过设定的比例.-XX:+UseAdaptiveSizePolicy
: 设置Parallel Scavenge收集器具有自适应调节策略
在jdk1.5时期, HotSpot推出了一款在强交互应用中几乎可认为有划时代意义的垃圾收集器:CMS(Concurrent-Mark-Sweep)收集器, 这款收集器是HotSpot虚拟机中第一款真正意义上的并发收集器, 它第一次实现了让垃圾收集线程与用户线程同时还工作
CMS收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时间.
CMS的垃圾收集算法采用标记-清除算法, 并且也会"Stop-the-World"
不幸的是, CMS作为老年代的收集器, 却无法与JDK1.4.0中已经存在的新生代收集器Parallel Scavenge配合工作, 所以在JDK1.5中使用CMS来收集老年代的时候, 新生代只能选择ParNew或者Serial收集器中的一个
在G1出现之前, CMS使用非常广泛.
CMS整个过程比之前的收集器要复制, 整个过程分为4个主要阶段, 即初始标记阶段, 并发标记阶段, 重新标记阶段和并发清除阶段.
初始标记(Initial-Mark)阶段
在这个阶段中, 程序中所有的工作线程都将会因为"Stop-the-World"机制而出现短暂的暂停, 这个阶段的主要任务仅仅只是标记除GC Roots能直接关联到的对象. 一旦标记完成之后就会恢复之前暂停的所有应用线程. 由于直接关联对象比较小, 所以这里的速度非常块.
并发标记(Concurrent-Mark)阶段
从GC Roots的直接关联对象开始遍历整个对象图的过程, 这个过程耗时较长但是不需要停顿用户线程, 可以和垃圾收集线程一起并发运行
重新标记(Remark)阶段
由于在并发标记阶段中, 程序的工作线程会和垃圾收集线程同时运行或者交叉运行, 因此为了修正并发标记期间, 因为用户程序继续运作而导致标记产生变动的那部分对象的标记记录, 这个阶段段的停顿时间通常会比初始标记阶段稍长一些, 但也远比并发标记阶段的时间短.(这个阶段也需要STW)
怀疑是垃圾, 然后再次确认
并发清除(Concurrent-Sweep)阶段
此阶段清除删除掉标记阶段判断的已经死亡的对象, 释放内存空间. 由于不需要移动存活对象, 所以这个阶段也是可以与用户线程同时并发的.
会产生内存碎片
CMS收集器堆CPU资源非常敏感
CMS收集器无法处理浮动垃圾
重新标记阶段是将之前怀疑是垃圾的部分对象再次确认, 但是无法清除原先不是垃圾, 但是在重新标记阶段编程垃圾的部分对象, 这部分对象称为浮动垃圾
-XX:+Use G1GC
来启用.与其他GC收集器相比, G1使用了全新的分区算法, 其特点如下
G1的设计原则就是简化JVM性能调优, 开发人员只需要简单的三步即可完成调优
G1中提供了三种垃圾回收模式: YoungGC, Mined GC和Full GC, 在不同的条件下被触发.
根据具体的情况选用不同的垃圾收集器
GC发展阶段
Serial => Parallel(并行) => CMS(并发) => G1 => ZGC
不同厂商, 不同版本的虚拟机实现差别很大. HotSpot虚拟机在JDK7/8后所有收集器及组合(连线)
-XX:+PrintGC
: 输出GC日志. 类似: -verbose:gc
-XX:+PrintGCDetails
: 输出GC详细日志
-XX:+PrintGCTimeStamps
: 输出GC的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps
: 输出GC的时间戳(以日期的形式)
-XX:+PrintHeapAtGC
: 在进行GC的前后打印出堆的信息
-Xloggc:../logs/gc.log
: 日志文件的输出路径
“GC"和"Full GC"说明了这次垃圾收集的停顿类型, 如果有"Full"则说明GC发生了"STW”
使用Serial收集器在新生代的名字是Defaul New Generation, 因此显示的是"DefNew"
使用ParNew收集器在新生代的名字是Parallel New Generation, 因此显示的是: “ParNew”
使用Parallel Scavenge收集器在新生代的名字是"PSYoungGen"
老年代的收集和新生代道理一样, 名字也是收集器决定的
使用G1收集器的话, 会显示为"garbage-first heap"
Allocation Failure
表明本次引起GC的原因是因为在年轻代中没有足够的空间能够存储新的数据了
[PSYoungGen: 5986K->696K(8704K)] 5986K->704K(9216K)
中括号内: GC回收前年轻代大小, 回收后大小, (年轻代总大小)
括号外: GC回收前年轻代和老年代大小, hi售后大小, (年轻代和老年代总大小)
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。