
因为GC时,尽可能要让垃圾回收器专心工作,不能随便让我们写的Java系统继续新建对象了,所以此时JVM会在后台直接进入“Stop the World”:停止Java系统所有工作线程,让我们写的代码无法再运行!然后让GC线程能安心执行GC:
这就能让我们的系统暂停运行,不再创建新对象,同时让GC线程尽快完成GC工作:标记和转移Eden及Survivor2的存活对象到Survivor1,然后快速地一次性回收掉Eden和Survivor2中的垃圾对象:
GC完毕,即可继续恢复Java系统的工作线程运行,继续在Eden创建新对象:
Stop the World造成的系统停顿
假设Minor GC要运行100ms,则可能导致系统直接停顿100ms,不能处理任何请求。这100ms期间用户发起的所有请求都会出现短暂卡顿,因为系统工作线程不在运行,不能处理请求。假设是Web系统,可能导致你的用户从网页或APP点击一个按钮,平时只要几十ms就可以返回响应,现在因为Web系统JVM正在执行Minor GC,暂停所有工作线程,导致你的请求过来到响应返回,这次需等待几百ms。
影响停顿时间的原因:
1、因为内存分配不合理:导致对象频繁进入老年代,平均7、8min一次Full GC,而Full GC最慢,有时一次回收要进行几s甚至几十s。此时一旦频繁Full GC,你的系统每隔几min就会卡死几十s。这让用户体验极差。所以无论新生代GC还是老年代GC,都尽量不能频繁,也要避免持续时间过长。
2、不同的垃圾回收器的不同的影响:新生代的回收,Serial垃圾回收器就是用1个线程进行垃圾回收,然后此时暂停系统工作线程,所以一般服务器程序中很少用。平时常用的新生代垃圾回收器是ParNew,其针对服务器一般都是多核CPU有优化,支持多线程GC,可大幅提升回收性能,缩短GC时间。