“Stop the World”简单分析

1.引言

有一个问题,GC的时候还能创建新的对象吗?

假设允许GC期间,还可以继续让系统在年轻代的Eden区里创建新的对象,会是什么样的场景?

“Stop the World”简单分析

根据上图所示,如果垃圾回收器一边想办法将Eden和Survivor2区里的存活对象标记出来转移到Survivor1区,然后还在想办法把Eden和Survivor2区里的垃圾对象清理掉,结果这个时候系统程序还在不停地在Eden里创建新的对象。

 

这些新的对象有的很快成为了垃圾对象,有点是还有人引用的存活对象,怎么办?

其实在垃圾回收过程中,同时还允许我们写的java系统继续不停的运行在Eden里持续创建新的对象,目前来看是非常不合适的一个事情。

 

2.JVM的痛点:Stop the World

因为在垃圾回收的时候,尽可能要让垃圾回收器专心致志的工作,不能随便让我们写的java系统继续创建对象了,所以此时JVM会在后台直接进入“Stop the World”状态。

也就是说,会直接停止我们写的Java系统的所有工作线程,让代码不再余下

然后让垃圾回收线程可以专心致志的进行垃圾回收的工作,如下图:

“Stop the World”简单分析

接着一旦垃圾回收完毕,就可以继续恢复我们写的Java系统的工作线程运行了。然后那些代码就可以继续运行,继续在Eden中创建新的对象。

 

3.Stop the World造成的系统停顿

根据上述分析,可以看出"Stop the World"会对系统造成的影响,假设我们的Minor GC要运行100ms,那么可能会导致我们的系统之间停顿100ms不能处理任何请求

在这期间,用户发起的所有请求都会出现短暂的卡顿

假设因为内存分配不合理,导致对象频繁进入老年代,平均七八分钟一次Full GC,而Full GC是最慢的,有时候弄不好一次回收要进行几秒钟,甚至几十秒,有些极端场景几分钟都是有可能的。

那么此时一旦频繁的Full GC,难道你希望系统每隔七八分钟就卡死个30秒吗?

所以说,无论是Minor GC还是Full GC,尽量不要让频率过高,也避免持续时间过长,避免影响系统正常运行,这也是使用JVM过程中一个最需要优化的地方,也是最大的一个痛点。