
按工作模式:
按碎片处理方法:
按工作的内存区间:
在最大吞吐量优先的情况下,降低暂停时间



连线表示组合关系,虚拟表示废弃的组合或收集器


客户端模式下默认的新生代垃圾收集器(因为它在单CPU下性能不错)
采用复制算法
串行回收且使用STW机制
采用标记压缩算法
串行回收且使用STW机制
客户端模式下默认的老年代垃圾收集器(因为它在单CPU下性能不错)
在服务端主要有两种用途:
-XX:+UserSerialGC可以指定年轻代和老年代都使用Serial收集器

Serial收集器的多线程版本
只能处理新生代
采用复制算法
并行回收且使用STW机制
很多JVM在服务端模式下默认的新生代垃圾收集器
对于新生代,由于回收次数频繁,所以使用并行方式高效;对于老年代,由于回收次数少,所以使用串行方式节省资源(多线程需要切换,消耗资源)。ParNew在新生代是并行回收,是不是就一定比Serial收集器高效?No!要分在单CPU环境还是多CPU环境
-XX:+UserParNewGC可以指定年轻代使用ParNew
-XX:ParallelGCThreads限制线程数量

在年轻代中ParNew收集器已经基于并行回收了,为什么还要Parallel Scavenge收集器?
高吞吐量可以高效利用CPU时间,尽快完成程序的运算任务,适合在后台计算且不需要太多交互的任务(如订单处理等)
-XX:+UserParallelGC可以指定年轻代使用Parallel Scavenge;-XX:+UserParallelOldGC可以指定老年代使用Parallel Old(这两个参数一个开启,默认另一个也会被开启)
-XX:ParallelGCThreads限制线程数量
CMS:Concurrent-Mark-Sweep,JDK14已经被删除

CMS整个过程分为四个阶段:
初始标记阶段:用户线程会STW,垃圾回收线程只是标记出GC Roots能直接关联的对象,标记完就恢复线程,因为直接关联对象少,所以该阶段执行速度快
并发标记:从GC Roots的直接关联对象开始遍历所有对象,耗时较长但是不需要暂停用户线程
重新标记:在并发标记阶段,由于用户线程没有暂停所以可能会出现对象的变动。该阶段修正那部分变动对象的标记记录(被修正的变动对象是值原来是垃圾但是变更为非垃圾的对象,并不是因为用户线程执行由非垃圾而变为垃圾的对象),相较于并发标记阶段时间短,但是用户线程需要STW
并发清除:清理标记阶段判断已死亡的对象,释放内存空间。由于不需要移动存活对象,所以该阶段可以与用户线程并发执行(不需要STW)
低延迟适用于与用户交互的程序,比如B/S系统的服务端与网站
Full GC由于在CMS垃圾收集中用户线程没有中断,所以要确保用户线程由足够内存可以使用,所以CMS不能等老年代完全被填满再收集,而是等堆内存使用率达到阈值后开始回收。
如果预留内存无法满足用户线程使用,则出现
Concurrent Mode Failure,JVM会临时启动Serial Old重新进行老年代收集(用户线程停顿时间就变长了)
标记清除算法会产生内存碎片,为什么不使用标记压缩算法?
采用压缩算法整理内存时,对象地址会被修改,而用户线程还在运行,其使用的内存被压缩整理后无法使用
-XX:+UserConcMarkSweepGC可以指定老年代使用CMS,开启后会自动开启ParNew
目标是在延迟可控(即低的STW时间)的情况下获得尽可能高的吞吐量
把堆划分为不相关的区域Region(物理上不连续),用于表示Eden区、survivor0、survivor1、老年代等
进行全区域的垃圾回收
每次根据允许的收集时间,优先回收价值较大的Region(Garbage First命名由来):
针对多核CPU和大容量内存的机器(如服务端应用)
JDK9后默认垃圾回收器
-XX:+UseG1GC:指定G1收集器
-XX:G1HeapRegionSize:设置Region的大小
-XX:MaxGCPauseMillis:设置期望达到的最大GC停顿时间指标

为什么要设置H?对于堆中的大对象默认直接放到老年代,但如果它只是短期存在的大对象,而老年代回收频率低,相当于内存泄漏(该对象要被收集却因为清除频率低未被收集),所以使用H区装大对象(如果一个H区装不下就找连续的H区,找不到连续的H区就Full GC)
一个Region对象可能会被其他Region引用,意味着回收年轻代时还需要扫描老年代(即对整个堆进行扫描,相当于Full GC了),降低了GC效率,如何避免这种扫描?
每个Region都有对应的一个Remembered Set
对每个引用类型数据进行写操作时(即引用其他对象),会产生一个写屏障暂停中断,然后检查要引用的对象是否和引用类型数据在同一个Region中:
CardTable把引用信息记录到引用类型对象所在的Region的Remembered Set(记录这个Region清理时需要扫描哪几个Region,判断其他Region是否还引用它)垃圾收集时,把Remembered Set加入到GC Roots(回收年轻代时,老年代的对象相当于GC Roots)的枚举范围中

首先G1停止应用程序,并且创建回收集(需要被回收的内存分段集合,年轻代GC时该集合包括所有Eden区和Survivor区)
然后开始以下过程:
Remembered Set引用的对象(避免全堆扫描)Remembered Set,保证Remembered SetRemembered Set回收全部年轻代和部分老年代
