1. JVM 垃圾回收器简介及Stop the World问题

1.1. 垃圾回收器简介

在新生代和老年代进行垃圾回收的时候,都是要用垃圾回收器进行回收的,不同的区域用不同的垃圾回收器

1.1.1. Serial和Serial Old垃圾回收器

分别用来回收新生代和老年代的垃圾对象,工作原理就是单线程运行,垃圾回收的时候会停止自己的系统的其他工作线程,让系统直接卡死不动,然后垃圾回收,后台Java系统现在一般几乎不会使用。

1.1.2. ParNew和CMS垃圾回收器

ParNew是现在一般用在新生代的垃圾回收器,CMS是用在老年代的垃圾回收器,都是多线程并发的机制,性能更好,一般是线上生产系统的标配组合。

1.1.3. G1垃圾回收器

统一收集新生代和老年代,采用了更加优秀的算法和设计机制。

1.2. Stop the World问题

1.2.1. 回顾新生代 GC 流程

新生代快满的时候,发生垃圾回收,会将存活对象,放到 空白的S区,两块 S区 交替使用,如下图所示。

gc_copy_algorithm_optimize01 gc_copy_algorithm_optimize02 gc_copy_algorithm_optimize03 gc_copy_algorithm_optimize04

1.2.2. GC 的时候可以创建新对象吗

之前介绍垃圾回收的时候,没有提到是否可以创建对象,在这里来介绍一下。

假如 GC 期间,还可以创建对象,会有什么问题呢?

新生代使用复制算法,GC 过程中,回收线程将存活对象移动到 Survivor区,这时候创建新的对象,会放在 Eden区,当要回收的时候可能会有新创建的对象,还有重新处理,会增加回收的复杂性,成本极高,很难做到。所以回收过程中可以创建新对象是非常不合适的

jvm_gc_stw_01

1.2.3. Stop the World问题

什么是Stop the World

在垃圾回收的时候,让垃圾回收器专心致志的工作,所以不能让Java系统继续创建对象,此时JVM会直接进入Stop the World状态。

JVM会直接停止Java系统的所有工作线程,让业务系统的代码不再运行!然后垃圾回收线程可以专心致志的进行垃圾回收的工作。

jvm_gc_stw_02

系统不再创建新的对象时,同时垃圾回收线程会尽快完成垃圾回收的工作,标记和转移Eden以及Survivor2的存活对象到Survivor1中,一次性回收掉Eden和Survivor2区域。

jvm_gc_stw_03

垃圾回收完毕,业务系统的工作线程就可以继续运行了,继续在Eden中创建新的对象。

jvm_gc_stw_04

Stop the World会有什么影响

假如Minor GC要运行100ms,则会导致系统直接停顿100ms不能处理任何请求。在这100ms期间用户发起的所有请求都会出现短暂的卡顿,因为系统的工作线程不在运行,不能处理请求。

可以思考一下,因为内存分配不合理,导致对象频繁进入老年代,平均七八分钟一次Full GC,而Full GC是最慢的,一些情况下一次回收要进行几秒钟,甚至几十秒,极端场景也可能是几分钟。

一旦频繁的Full GC,系统每隔七八分钟就卡死几十秒。在这期间任何用户的请求全部无法处理,用户看到的都是系统超时之类的提示,这会导致使用体验极差。

所以,无论是新生代GC还是老年代GC,都尽量不要频率过高,也避免持续时间过长,避免影响系统正常运行,这是使用JVM过程中一个最需要优化的地方。

results matching ""

    No results matching ""