原创天涯问路 最后发布于2019-12-05 14:46:21 阅读数 32 已收藏
展开
面试 GC 相关的问题有:
垃圾回收算法有哪些:引用计数、复制、标清、标压
垃圾收集器有哪些:Serial、Parallel、CMS、G1、ZGC
垃圾回收的方式有哪些:串行、并行、并发标记清理、分区并发------分别对应上方垃圾收集器
GC 算法(引用计数、复制、标清、标压)是理论,垃圾收集器是具体实现
主要垃圾收集器:
串行垃圾收集器-Serial:为单线程环境设计且只使用一个线程进行回收,会暂停所有的用户线程。所以不适合服务器环境
并行垃圾收集器-Parallel:多个垃圾回收线程并行工作,此时用户线程是暂停的,适用于科学计算、大数据处理、首台处理等弱交互场景
并发垃圾收集器-CMS(ConcMarkSweep):并发标记清除。用户线程和垃圾收集器线程同时执行(不一定是并行,也可能是交替执行),不需要暂停用户线程。互联网公司多用它,适用于对响应时间有要求的场景
G1-GarbageFirst:将对内存分割成不同的区域然后并发的进行垃圾回收
ZGC ( java11 之后新增 )
如何查看默认的垃圾收集器:
Terminal 输入命令:java -XX:+PrintCommandLineFlags -version
java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=267121280
-XX:MaxHeapSize=4273940480
-XX:+PrintCommandLineFlags
-XX:+UseCompressedClassPointers
-XX:+UseCompressedOops
-XX:-UseLargePagesIndividualAllocation
-XX:+UseParallelGC
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)
可以看到 -XX:+UseParallelGC ,即使用的是并行垃圾收集器
默认垃圾收集器有:
UseSerialGC
UseSerialOldGC(已弃用)
UseConcMarkSweepGC
UseParNewGC
UseParallelGC
UseParallelOldGC
UseG1GC
由上图可知,新生代(Young Gen)用 Serial、Parallel、ParNew这三种垃圾收集器;老年代(Old Gen)用SerialOld、ParallelOld、ConcMarkSweep这三种垃圾收集器。而G1两者都可用。
项目中如何选择垃圾收集器
单 CPU 或小内存,单机程序: -XX:+UseSerialGC
多 CPU ,需要大吞吐量,如后台计算型应用:-XX:+UseParallelGC 或者 -XX:+UseParallelOldGC
多 CPU,追求低停顿时间,需快速响应如互联网应用:-XX:+UseConcMarkSweepGC 或者 -XX:+UseParNewGC
如何查看当前用的是哪个垃圾收集器:
Terminal输入命令:jps -l ,获取进程编号
Terminal输入命令:jinfo -flag UseParallelGC 进程编号,输出 -XX:+UseParallelGC 说明是用的该类收集器;输出 -XX:-UseParallelGC 说明不是该类收集器。+相当于是,-相当于不是。
G1垃圾收集器
G1-GarbageFirst 是一种服务器端的垃圾收集器,应用在多处理器和大容量内存环境中,在实现高吞吐量的同时,尽可能满足垃圾收集暂停时间的要求。另外还有以下特性:
与 CMS 收集器一样,可以和应用程序并发执行
整理空闲空间更快
需要更多的时间来预测 GC 的停顿时间
不希望牺牲大量的吞吐性能
不需要大量的 Java Heap
相比之下,以前收集器的特点:
年轻代和老年代是各自独立且连续的内存块
年轻代收集使用单 eden+S0+S1进行复制算法
老年代收集必须扫描整个老年代区域
都是以尽可能少而快速的执行GC为设计原则
CMS 收集器虽然减少了暂停应用程序的运行时间,但还是存在着内存碎片的问题,于是,为了解决内存碎片的问题,同时又保留低暂停时间的有点,Java7 就发布了一个 G1垃圾收集器。
G1 收集器的设计,目的就是为了取代 CMS 收集器,G1 与 CMS 相比,有何区别?(面试题)
有整理内存过程,不会产生很多内存碎片
STW(Stop The World)更可控,G1 在停顿时间上添加了预测机制,让用户可以手动配置停顿时间
G1 是在 2012年才在jdk1.7u4中可用。oracle计划在jdk9中将 G1 变成默认的垃圾收集器以替代 CMS 。它是一款面向服务端应用的收集器,主要应用在多 CPU 和大内存服务器环境下,极大减少垃圾收集的停顿时间,全面提升服务器的性能,逐步替换 java8 以前的 CMS 收集器。
主要改变是 Eden、Survivor和Tenured等内存区域不是连续的了,而是变成了一个个大小一样的 region,每个region从1M到32M不等,一个 region 可能属于 Eden、Survivor 或者 Tenured内存区域。
G1 特点总结:
能充分利用多 CPU、多核环境的硬件优势,尽量缩短 STW
整体上采用 “标记-压缩” 算法,局部使用 “复制” 算法,不会产生内存碎片
宏观上不再区分 “老年代” 和 “新生代” ,把内存划分成独立的子区域 —Region
将整个内存区域混合在一起,但其本身依然在小范围内要进行年轻代和老年代的区分,保留了新生代和老年代,但他们不再是物理隔离的,而是一部分 Region 的集合且不需要 Region是连续的,也就是说依然会采用不同的 GC 方式来处理不同区域
G1 虽然也是分代收集器,但整个内存区不存在物理上的年轻代和老年代的区别,也不需要完全独立的survivor(to space)堆做复制准备。G1 只有逻辑上的分代概念,或者说每一个分区都可能随 G1 的运行在不同的代之间前后切换。
最大的好处是化整为零,避免全内存扫描,只需按照区域扫描。
————————————————
版权声明:本文为优快云博主「天涯问路」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/S_Alics/article/details/103364110
1927

被折叠的 条评论
为什么被折叠?



