最近在看jvm gc 相关的内容,想看一下jdk1.8 默认的垃圾回收器,然后输入命令来查看
java -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -version
可以发现 jdk 1.8 默认的 垃圾收集器 是 ParallelGC 在新生代使用的是 PSYoungGen,也就是 Parallel Scavenge, 老年代是使用的 ParOldGen,这是一款以吞吐量为目标的垃圾收集器。
然后我在换另外一台机器使用同样的命令,然后发现问题了
同样的操作系统和jdk 版本,但是发现默认没有使用 ParallelGC,这个就很奇怪了,一开始以为是环境或者软件问题,排查了很久都没有发现,使用以下命令发现 ParallelGC 也是关闭的
java -XX:+PrintFlagsFinal -version | grep "GC"
后面想是不是和硬件有关系呢,后面那台虚拟机只有1核cpu ,而ParallelGC 是并发收集器,jvm 监测硬件发现不支持,所以给它关了。然后我调整虚拟机核心数,发现 ParallelGC 果然启用了。看来就是cpu 核心数不同导致 垃圾回收器也不同,虽然单核没有打印回收器是什么,但是我猜测使用的是 Serial 单线程的垃圾回收器。
我们就在此来学习一下目前jvm 常用的垃圾回收器吧
新生代收集器:
Serial
ParNew
Parallel Scavenge
老年代收集器:
Serial Old
CMS
Parallel Old
堆内存垃圾收集器:
G1
ZGC
Serial
是最古老的单线程垃圾回收器,分为新生代 Serial,和 老年代 Serial Old,适合单核cpu,做垃圾回收时,用户线程需要等回收完才能继续工作, stop the world 可能会比较长
ParNew
新生代 Serial 的多线程版本,可以提高回收效率,以减少 stop the world 为目标,通常配合cms 使用。其他并发收集器不能和cms 同时使用。
Parallel GC
也是多线程并发收集器,分为 新生代 Parallel Scavenge和老年代 Parallel Old,与 ParNew不同的是它以提高吞吐量为目标,也是jdk1.8默认的垃圾回收器(机器为多核的)
cms
多线程并发收集器,只能在老年代使用,以减少 stop the world 为目标,通常配合ParNew使用,
g1
G1 进行垃圾收集的范围是整个堆内存,它采用 “ 化整为零 ” 的思路,把整个堆内存划分为多个大小相等的独立区域(Region),在 G1 收集器中还保留着新生代和老年代的概念,它们分别都是一部分 Region,如下图
zgc
ZGC是在G1的基础上发展起来的,ZGC 在更多的地方(复制和压缩,复制集的选择)使用了并发,所以
- 支持TB级内存
- 停顿时间控制在10ms之内
-
对程序吞吐量影响小于15%
目前市面上的主流仍然是 Parallel GC 或者 ParNew + cms
在互联网项目中,尽量提高用户体验,减少停顿时间,使用 ParNew + cms ,在一些后台计算的应用,使用 Parallel GC,提高吞吐量。