JVM-044-垃圾回收-相关概念的概述-Stop The World

概念

Stop-the-World,简称STW,指的是GC事件发生过程中,会产生应用程序的停顿。停顿产生时整个应用程序线程都会被暂停,没有任何响应,有点像卡死的感觉,这个停顿称为STW。

为什么会有STW

可达性分析算法中枚举根节点(GC Roots)会导致所有Java执行线程停顿:

  • 分析工作必须在一个能确保一致性的快照中进行
  • 一致性指整个分析期间整个执行系统看起来像被冻结在某个时间点上
  • 如果出现分析过程中对象引用关系还在不断变化,则分析结果的准确性无法保证

说明

  • 被STW中断的应用程序线程会在完成GC之后恢复,频繁中断会让用户感觉像是网速不快造成电影卡带一样,所以我们需要减少STW的发生。
  • STW事件和采用哪款GC无关,所有的GC都有这个事件。
  • 哪怕是G1也不能完全避免Stop-the-world情况发生,只能说垃圾回收器越来越优秀,回收效率越来越高,尽可能地缩短了暂停时间。
  • STW是JVM在后台自动发起和自动完成的。在用户不可见的情况下,把用户正常的工作线程全部停掉。
  • 开发中不要用System.gc() ,这会导致Stop-the-World的发生。

举例证明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class StopTheWorldDemo {
public static class WorkThread extends Thread {
List<byte[]> list = new ArrayList<byte[]>();

public void run() {
try {
while (true) {
for(int i = 0;i < 1000;i++){
byte[] buffer = new byte[1024];
list.add(buffer);
}

if(list.size() > 10000){
list.clear();
System.gc();//会触发full gc,进而会出现STW事件

}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

public static class PrintThread extends Thread {
public final long startTime = System.currentTimeMillis();

public void run() {
try {
while (true) {
// 每秒打印时间信息
long t = System.currentTimeMillis() - startTime;
System.out.println(t / 1000 + "." + t % 1000);
Thread.sleep(1000);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

public static void main(String[] args) {
WorkThread w = new WorkThread();
PrintThread p = new PrintThread();
w.start();
p.start();
}
}
  1. 关闭工作线程 w ,观察输出:当前时间间隔与上次时间间隔基本是每隔1秒打印一次

    1
    2
    3
    4
    5
    6
    7
    8
    0.1
    1.1
    2.2
    3.2
    4.3
    5.3
    6.3
    7.3
  2. 开启工作线程 w ,观察打印输出:当前时间间隔与上次时间间隔相差 1.3s ,可以明显感受到 Stop the World 的存在

    1
    2
    3
    4
    5
    6
    0.1
    1.4
    2.7
    3.8
    4.12
    5.13

JVM-044-垃圾回收-相关概念的概述-Stop The World

https://blog.buubiu.com/JVM-044-垃圾回收-相关概念的概述-Stop-The-World/

作者

buubiu

发布于

2024-01-05

更新于

2024-11-28

许可协议