目录
(1)Serial收集器(新生代串行GC/Servial Copying)
(3)Parallel(并行回收GC/Parallel Scavenge)
1 概述
- 问题1:垃圾回收算法和垃圾回收器有什么关系?
- 垃圾回收算法是垃圾回收的方法论,垃圾收集器是垃圾回收算法的具体实现
- 问题2:为什么有这么多种垃圾回收器?
- Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,
- 因此不同厂商、不同版本的虚拟机所提供的垃圾收集器都有可能有很大差别
- 目前为止,还没有完美的收集器出现,Java的应用场景很多,没有万能的收集器能解决所有应用场景,只是针对具体应用选择最合适的收集器,进行分代收集
- 问题3:如何查看默认的垃圾回收器?
- java -XX:+PrintCommandLineFlags -version
垃圾收集器的底层配置代码:
2 八大垃圾收集器
代码后结果的参数提前说明:
- DefNew:Defalut New Generation,默认新生代
- Tenured:Old,老年代
- ParNew:Parallel New Generation,在新生代用并行回收
- PSYoungGen:Parallel Scavenge
- ParOldGen:Parallel Old Generation,在老年代用并行回收
JVM中Server/Client分别是什么意思:
- 适用范围:只需要掌握Server模式,Client基本不会用
- 操作系统:
- 32位Window操作系统,不论硬件如何都默认使用Client的JVM模式
- 32位其他操作系统,2G内存同时有2个CPU以上使用的是Server模式,低于该配置还是Client模式
- 64位的操作系统都是Server模式
2.1 新生代垃圾收集器
(1)Serial收集器(新生代串行GC/Servial Copying)
- 它是最早使用的一个收集器,在JDK1.3.1之前是唯一的选择
- 一个单线程的收集器:即在垃圾回收的时候只会使用一个CPU或一个收集线程完成垃圾回收工作
- 在进行垃圾收集的时候,必须暂停其他所有的工作线程直到它收集结束
- 如图:
- 一对一:新生代和老年代都为单线程
- 说明:STW即为Stop The World,即暂停所有应用程序线程
优点:
- 简单而高效
- 对于限定单个CPU环境来说,没有线程交互的开销可以获得最高的单线程垃圾收集效率
缺点:
- 收集期间需要暂停所有应用线程,用户体验不好
应用场景:
- Java虚拟机运行在Client模式下默认的新生代垃圾收集器
对应JVM参数是:-XX:+UseSerialGC
- 当我们使用此参数开启Serial,老年代默认会开启Serial Old
- 即开启后会使用:Serial(Young区用)+Serial Old(Old区用)的收集器组合
- 表示新生代和老年代都会使用串行回收收集器
- 新生代使用复制算法,老年代使用标记-整理算法
示例代码演示:
import java.util.Random;
public class GCDemo {
public static void main(String[] args) {
System.out.println("=====GCDemo,Hello====");
try {
String str = "GCDemo";
while (true){
str += str + new Random().nextInt(77777777) + new Random().nextInt(88888888);
str.intern();
}
}catch (Throwable e){
e.printStackTrace();
}
}
}
配置JVM参数:
结论:DefNew+Tenured
(2)ParNew(新生代并行GC)
- 使用多线程进行垃圾回收
- 在进行垃圾收集的时候,必须暂停其他所有的工作线程直到它收集结束
- 如图:
- ParNew收集器其实是Serial收集器新生代的并行多线程版本
应用场景:
- 最常见的应用场景是配合老年代的CMS GC工作,其余的行为和Serial收集器完全一样
- 它是很多Java虚拟机运行在Server模式下新生代的默认垃圾收集器
对应JVM参数是:-XX:+UseParNewGC
- 启用ParNewGC收集器,只影响新生代的收集,不影响老年代
- 开启后会使用:ParNew(Young区用)+Serial Old(Old区用)的收集器组合
- 新生代使用复制算法,老年代使用标记-整理算法
备注:
- -XX:ParallelGCThreads 限制线程数量,默认开启和CPU数目相同的线程数
示例代码演示:
import java.util.Random;
public class GCDemo {
public static void main(String[] args) {
System.out.println("=====GCDem