Pre
JVM-04垃圾收集Garbage Collection(上)【垃圾对象的判定】
JVM-05垃圾收集Garbage Collection(中)【垃圾收集算法】
JVM-06垃圾收集Garbage Collection(下)【垃圾收集器】
分代收集理论
当前虚拟机的垃圾收集都采用分代收集算法 , 意思就是根据对象存活周期的不同将 java堆分为新生代和老年代,这样就可以根据各个年代的特点选择合适的垃圾收集算法。
举个例子,新生代中,大部分对象都是朝生夕死的,所以可以选择复制算法, 只复制那些少量存活的对象。
而老年代,绝大部分都是一些顽固的对象,存货周期较长,如果选择复制算法,就要复制很多对象,效率自然不高 ,所以得换个算法,通常会选择标记-清除”或“标记-整理”算法进行垃圾收集。
常见的垃圾收集算法
标记-清除算法
两个阶段 “标记” + “清除”
- 标记存活的对象, 也可以反过来,标记出所有需要回收的对象
- 标记完成后,统一回收所有未被标记的对象(一般选择这种)
存在两个问题
- 如果需要标记的对象太多,效率不高 【效率问题】
- 标记清除后会产生大量不连续的碎片 【内存碎片】
基于这个缺点,进化除了 标记-整理 ,多了一步整理内存碎片。
标记-复制算法
它将内存分为大小相同的两块,每次使用其中的一块。
当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。
这样就使每次的内存回收都是对内存区间的一半进行回收。
- 优点:常用于新生代,存活的对象少,复制这些存活的对象,效率高。
- 缺点 显而易见: 浪费空间
标记-整理算法
根据老年代的特点演化出一种标记算法, 标记过程同“标记-清除” 。
移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收。因此,第二阶段才称为整理阶段。
垃圾收集器
为什么会有这么多GC 回收器?
因为目前没有任何一款是十分完美的,我们需要做的就是充分了解这些GC Collector 根据业务特点选择合适的GC Collector 。
Serial收集器
两个收集器 。一个 新生代Serial , 一个 老年代 Serial Old .
新生代采用复制算法,老年代采用标记-整理算法。
JVM参数
-XX:+UseSerialGC (新生代) -XX:+UseSerialOldGC (老年代)
Serial(串行)收集器是最基本、历史最悠久的垃圾收集器 。
字面意思:
- 单线程GC
- GC的时候STW
- 新生代 Serial , 复制算法
- 老年代Serial Old , 标记整理算法
Serial Old收集器是Serial收集器的老年代版本,也是一个单线程收集器。
它主要有两大用途:
- 一种用途是在JDK1.5以及以前的版本中与Parallel Scavenge收集器搭配使用,
- 另一种用途是作为CMS收集器的后备方案。
Parallel Scavenge收集器 【JDK8默认】
Serial收集器的多线程版本
JVM参数
-XX:+UseParallelGC(年轻代),-XX:+UseParallelOldGC(老年代)
默认的收集线程数跟cpu核数相同,当然也可以用参数(-XX:ParallelGCThreads)指定收集线程数,但是一般不推荐修改。
Parallel Scavenge收集器关注点是吞吐量(高效率的利用CPU)
CMS等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验)
新生代采用复制算法,老年代采用标记-整理算法。
Parallel Old收集器是Parallel Scavenge收集器的老年代版本。使用多线程和“标记-整理”算法。
在注重吞吐量以及CPU资源的场合,都可以优先考虑 Parallel Scavenge收集器和Parallel Old收集器(JDK8默认的新生代和老年代收集器)。
ParNew收集器
What ? ParNew ? 不是有个Parallel 吗? 又出来这个主要是因为Parallel 不能和CMS搭配使用,所以官方又弄出个这么个玩意儿。
JVM参数
-XX:+UseParNewGC
ParNew收集器其实跟Parallel收集器很类似,区别主要在于它可以和CMS收集器配合使用。
新生代采用复制算法,老年代采用标记-整理算法。
互联网公司 小内存的机器 主流的GC组合 就是 ParNew + CMS .
CMS 【重点掌握】
JVM参数
-XX:+UseConcMarkSweepGC(老年代)
详细的四个步骤、CMS存在的问题以及三色标记我们下篇博文继续展开