java面试-垃圾回收器谈谈你的理解
一、垃圾回收算法:
- 引用计数
- 复制算法
- 标记-清除
- 标记-整理
二、垃圾回收的方式:
串行(Serial)、并行(Parallel)、并发(CMS)、G1
1、串行垃圾回收器(Serial)
- 它为单线程环境设计且只使用一个线程进行垃圾回收,会暂停所有的用户线程,所以不适合服务器环境。
2、并行垃圾回收器(Parallel)
- 多个垃圾收集线程并行工作,此时用户线程是暂停的,用于科学计算、大数据处理等弱交互场景。
3、并发垃圾回收器(CMS)
- 用户线程和垃圾收集线程同时执行(不一定是并行,可能是交替执行),不需要停顿用户线程,互联网公司多用它,适用对相应时间有要求的场景。
4、G1 垃圾回收器
- G1 垃圾回收器将堆内存分割成不同的区域然后并发的对其进行垃圾回收。
三、如何查看默认的垃圾收集器是哪一个?
java -XX:+PrintCommandLineFlags -version
四、默认的垃圾收集器有哪些?
UseSerialGC,UseParallelGC,UseConcMarkSweepGC,UseParNewGC,UseParallelOldGC,UseG1G
五、垃圾收集器
Java 8 以后基本不使用 Serial Old
配置新生代收集器,老年代收集器会自动配置上
- 新生代
- 串行 GC (Serial)
- 并行 GC (ParNew):配置-XX:+UseParNewGC,新生代并行,老年代串行
- 并行回收 GC (Parallel Scavenge):
串行收集器在新生代和老年代的并行化,配置-XX:+UseParallelGC,新生代、老年代都是并行
可控的吞吐量
自适应调节策略
- 老年代
- 串行 GC (Serial Old)
- 并行 GC (Parallel Old)
- 并发标记清除 GC (CMS)
- 优点:并发收集停顿低
- 缺点:并发执行对 CPU 资源压力大,采用的标记清除算法会导致大量碎片
配置参数 | 新生代垃圾收集器 | 新生代垃圾收集算法 | 老年代垃圾收集器 | 老年代垃圾收集算法 |
-XX:+UseSerialGC | Serial | 复制算法 | Serial Old | 标记-整理算法 |
-XX:+UseParNewGC | ParNew | 复制算法 | Serial Old | 标记-整理算法 |
-XX:+UseParallelGC | Parallel Scavenge | 复制算法 | Parallel Old | 标记-整理算法 |
-XX:+UseParalleOldlGC | Parallel Scavenge | 复制算法 | Parallel Old | 标记-整理算法 |
-XX:+UseConcMarkSweepGC | ParNew | 复制算法 | CMS+Serial Old | 标记-清除算法 |
-XX:+UseG1GC | G1整体上采用标记-整理算法 | 局部是通过复制算法,不会产生内存碎片 |
代码验证:
/** * 1、-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseSerialGC (DefNew+Tenured) * * 2、-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseParNewGC (ParNew+Tenured)java8不再被推荐 * Java HotSpot(TM) 64-Bit Server VM warning: Using the ParNew young collector with the Serial old collector * is deprecated and will likely be removed in a future release * * 3、-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseParallelGC (PSYoungGen+ParOldGen) * * 4、-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseParallelOldGC (PSYoungGen+ParOldGen) * * 5、-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseConcMarkSweepGC (ParNew+CMS) * * 初始标记:CMS Initial Mark * 并发标记(和用户线程一起):CMS-concurrent-mark * 重新标记:CMS Final Remark * 并发清除(和用户线程一起):CMS-concurrent-sweep */ public class GCoverheadDemo { public static void main(String[] args) { int i = 0; List<String> list = new ArrayList<>(); while (true) { list.add(String.valueOf(++i).intern()); } } }
六、如何选择垃圾收集器?
- 单 CPU 或者小内存,单机程序:-XX:UseSerialGC
- 多 CPU 需要最大吞吐量,如后台计算型应用:-XX:UseParallelGC 或者 -XX:UseParallelOldGC
- 多 CPU 追求低停顿时间,需要快速响应,如互联网应用:-XX:+UseConcMarkSweepGC