JVM中的STW(Stop The World)

1. STW是什么?

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

2. STW出现的时机

  • 可达性分析算法中枚举根节点(GC Roots)会导致所有Java执行线程停顿。
  • 目前主流的虚拟机采用的都是可达性算法,算法的核心是利用根对象作为起始点,根据对象之间的引用关系,即引用链,通过遍历引用链来判断对象的是否存活。
  • 然而,可达性分析算法要求全过程都基于一个能保障一致性的快照中才能够进行分析,简单来说,就是必须全程冻结用户线程的运行。

3. 为什么必须冻结用户线程呢?

  • 因为,如果用户线程和垃圾回收线程并发执行,有可能会出现两个问题:浮动垃圾 和 对象消失,详情参考并发的可达性分析。

3.1 停顿的原因

a. 分析工作必须在一个能确保一致性的快照中进行
b. 一致性指整个分析期间整个执行系统看起来像被冻结在某个时间点上
c. 如果出现分析过程中对象引用关系还在不断变化,则分析结果的准确性无法保证
d. 停顿的位置:SafePoint (我也不理解)

3.2 什么是 SafePoint

SafePoint 就是一个安全点,可以理解为用户线程执行过程中的一些特殊位置。SafePoint 保存了当前线程的 上下文,当线程执行到这些位置的时候,说明线程当前的状态是 确定的,线程有哪些对象、使用了哪些内存。
因此,只有用户线程处于 SafePoint 的时候,线程才可以安全阻塞。
这意味着,Stop-The-World 需要所有的用户线程处于 SafePoint。

3.3 SafePoint 在哪些位置

SafePoint 插入到代码的某些位置,线程运行到 SafePoint 代码时,将会主动去检查是否需要进入 SafePoint,这个主动检查的过程,被称为 Polling 。
◉ 所有的非计数循环的末尾
(防止循环体的执行时间太长,一直进入不了 SafePoint)
◉ 所有方法返回之前
◉ 每条 Java 编译后的字节码的边界
SafePoint 的数量不能太少,因为这将会导致进入 SafePoint 的前置时间过长,以至于垃圾回收线程等待的时间太长。
SafePoint 的数量也不能太多,过于频繁的 Polling 会有性能损耗。

3.4 如何实现 STW/SafePoint

首先,Stop-The-World 需要所有的用户线程处于 SafePoint,这意味着某个用户线程运行到 SafePoint,其它用户线程可能处于不同的状态。
所有线程都到达GC Safepoint,有两种方法:
◉ 抢占式中断(Preemptive Suspension)
JVM会中断所有线程,然后依次检查每个线程中断的位置是否为Safepoint,如果不是则恢复用户线程,让它执行至 Safepoint 再阻塞。◉ 主动式中断(Voluntary Suspension)
大部分 JVM 实现都是采用主动式中断,需要阻塞用户线程的时候,首先做一个标志,用户线程会主动轮询这个标志位,如果标志位处于就绪状态,就自行中断。那么,针对用户线程的各种状态,需要怎么处理呢?
正在执行字节码解释器检查当前用户线程的标志,VM 线程调用以下方法阻塞线程。Interpreter::notice_safepoints()
正在运行 native 代码
如果 VM线程 发现一个当前用户线程正在执行 native 代码,不会等待线程阻塞。当线程从 native 代码返回时,检查 Safepoint 状态,如果处于 SafePoint,就直接阻塞线程。正在运行 JIT 编译好的代码
设置 Poling Page 为不可读,当前用户线程发现该内存页不可读时,就会被阻塞。
Poling Page:
在 JVM 初始化启动的时候,初始化的一个单独的内存页面,这个页面是让运行的编译过的代码的线程进入阻塞状态的关键,是一个全局的 Safepoint Polling Page。处于阻塞状态
在所有其他用户线程进入 SafePoint 之前,一直阻塞当前用户线程。处于线程切换状态
一直轮询该用户线程状态,直到线程处于阻塞状态。

参考:
JVM源码分析之安全点safepoint

3.5 SafePoint日志记录和分析

配置 -XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1 参数,

-XX:+PrintSafepointStatistics 打印安全点统计信息,
-XX:PrintSafepointStatisticsCount=n 设置打印安全点统计信息的次数;

3.6 日志分析:

1. vmop: 引发STW的原因,以及触发时间,本例中是GC。该项常见的输出有:RevokeBias、BulkRevokeBias、Deoptimize、G1IncCollectionPause。
数字306936.812是虚拟机启动后运行的秒数。GC log可以根据该项内容定位Total time for which application threads…引发的详细信息。vmop 输出说明RevokeBias、BulkRevokeBias、偏向锁取消情况。Deoptimize、G1IncCollectionPause GC GC 执行情况。
2. total : STW发生时,JVM存在的线程数目。
3. initially_running : STW发生时,仍在运行的线程数,这项是Spin阶段的 时间来源
4. wait_to_block : STW需要阻塞的线程数目,这项是block阶段的时间来源
5. sync = spin + block + 其他。

3.7 由日志可以看出safepoint的执行分为四个阶段:

1. Spin阶段。因为jvm在决定进入全局safepoint的时候,有的线程在安全点上,而有的线程不在安全点上,这个阶段是等待未在安全点上的用户线程进入安全点。
2. Block阶段。即使进入safepoint,用户线程这时候仍然是running状态,保证用户不在继续执行,需要将用户线程阻塞。
3. Cleanup。这个阶段是JVM做的一些内部的清理工作。
4. VM Operation. JVM 执行的一些全局性工作,例如 GC, 代码反优化。

3.8 优化说明

分析 -XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1 
产生的日志信息基本上STW的原因都是RevokeBias或者BulkRevokeBias。
这个是撤销偏向锁操作,虽然每次暂停的 时间很短,但是特别频繁出现也会很耗时。
一些高并发的系统中,禁掉JVM偏向锁优化,可以提升系统的吞吐量。
禁用偏向锁的参数为: -XX:-UseBiasedLocking

3.9 引起长时间STW原因

- GC
- RevokeBias 撤销偏向锁操作也会消耗很长时间。在高并发系统中,建议禁用偏向锁。
- 撤销偏向锁,增加 -XX:-UseBiasedLocking 虚拟机参数

4. 示例代码

  1. 被STW中断的应用程序线程会在完成GC之后恢复,频繁的中断会让用户感觉像是网速不快造成的电影卡顿一样,所以我们要减少STW的发生
  2. STW事件和采用哪款GC无关,所有的GC都有这个事件。
  3. 哪怕是G1也不能完全避免STW情况发生,只能说垃圾回收器越来越优秀,回收效率越来越高,尽可能地缩短了暂停时间。
  4. STW是JVM在后台自动发起和自动完成的。在用户不可见的情况下,把用户正常的工作线程全部停掉。
  5. 开发中采用System.gc();会导致STW的发生。
package com.zishi.jvm;import java.util.ArrayList;
import java.util.List;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();}
}

W线程当中的GC触发了STW,进而干扰了P线程有规律性打印。打印变得杂乱无章
打印输出:

0.0
1.100
2.103
3.112
4.122
5.134
6.143

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/137212.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

混合云中 DevOps 的最佳实践

近年来&#xff0c;出现了各种工具、技术和框架&#xff0c;其目标是增强灵活性、性能和可扩展性。传统的整体方法已被微服务和纳米服务等更加模块化的方法所取代。此外&#xff0c;云计算的兴起导致本地软件被云环境所取代&#xff0c;云环境提供了以前无法提供的广泛优势和功…

创建第一个Go的程序Hello Kitty

上一篇&#xff0c;我们已经搭建好了开发要用的基础环境:Go开发基础环境搭建, 今天我们要开始用GoLand实操关于Go的代码开发。 创建工程 File > New > Project 其中 game为项目名称 在项目目录下会自动生成一个文件:go.mod ,模块是相关Go包的集合。modules是源代码交换…

【ONE·C++ || 网络基础(二)】

总言 主要内容&#xff1a;演示socke套接字编程&#xff08;TCP模式&#xff09;&#xff0c;介绍序列化和反序列化&#xff0c;并进行演示&#xff08;json版本达成协议编写、守护进程介绍&#xff09;。 文章目录 总言4、基于套接字的TCP网络程序4.0、log.hpp4.1、version1.…

竞赛选题 深度学习疲劳驾驶检测 opencv python

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 &#x1f525; 优…

NSS [鹏城杯 2022]压缩包

NSS [鹏城杯 2022]压缩包 考点&#xff1a;条件竞争/逻辑漏洞&#xff08;解压失败不删除已经解压文件&#xff09; 参考&#xff1a;回忆phpcms头像上传漏洞以及后续影响 | 离别歌 (leavesongs.com) 源码有点小多 <?php highlight_file(__FILE__);function removedir($…

不想努力了,有没有不用努力就能考上硕士的方法

今年&#xff0c;硕士研究生考试报考人数再次刷新了纪录&#xff0c;高达474万人次。 这些年考研一直在扩招&#xff0c;但是录取率却越来越低&#xff0c;内卷血腥程度可想而知&#xff01; 2020年研究生报考人数341万&#xff0c;录取人数99.05万&#xff0c;录取率29.05%。…

物联网水表有什么弊端吗?

物联网水表作为新一代智能水表&#xff0c;虽然在很大程度上提高了水资源的管理效率&#xff0c;但也存在一定的弊端。在这篇文章中&#xff0c;我们将详细讨论物联网水表的弊端&#xff0c;以帮助大家更全面地了解这一技术。 一、安全隐患 1.数据泄露&#xff1a;物联网水表通…

Zabbix深入解析与实战

1.Zabbix 1.1.监控概述 监控是指对行为、活动或其他变动中信息的一种持续性关注&#xff0c;通常是为了对人达成影响、管理、指导或保护的目的 监控 监视主机架构状态控制&#xff0c;事后追责目标&#xff1a;早发现早处理(故障、性能、架构) 网站扩容(用数据说话) 为什么要…

基于SSM的社区生鲜电商平台

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

Google Analytics优缺点分析

Google Analytics是一款广泛使用的网站分析工具&#xff0c;它能够帮助网站和应用程序的拥有者收集和分析数据&#xff0c;并提供有关用户行为、流量来源和转化率等方面的详细见解。本文小编将讲讲关于Google Analytics的优缺点分析。 一、Google Analytics优点 1、免费使用&a…

万宾科技内涝积水监测仪使用效果一览

当一个城市突降暴雨&#xff0c;对城市管理部门来讲首当其中的是防止积水成患。随着城市人口快速增长&#xff0c;基础设施建设也日益受到更多的关注&#xff0c;城市内涝问题频繁增加&#xff0c;会给城市带来严重的经济损失和人员的安全问题。城市生命线工程建设过程中&#…

线程池创建、执行、销毁的原理解析

目录 线程池的执行原理线程执行参考&#xff1a; 线程池的执行原理 假设最大核心数是2&#xff0c;非核心线程数为1&#xff0c;队列长度是3 来第一个任务的时候&#xff0c;没有工作线程在工作&#xff0c;需要创建一个 来第二个任务的时候&#xff0c;发现当前核心线程数…

474. 一和零

给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度&#xff0c;该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素&#xff0c;集合 x 是集合 y 的 子集 。 示例 1&#xff1a; 输入&#xff1a;strs ["…

JS前端实现身份证号码合法性校验(校验码校验)

在做项目过程中针对自然人数据提交到后端前一般是要进行身份证的合法性校验&#xff0c;当身份证号输入错误以便给于用户友好的提示(也可以根据身份证号同时校验表单中性别和出生日期等)&#xff0c;验证主要是防止无效数据入库。本文在前端使用JavaScript实现15/18位身份证的合…

数字滤波器分析---零极点分析

数字滤波器分析---零极点分析 zplane 函数绘制线性系统的极点和零点。 例如&#xff0c;在 -1/2 处为零且在 0.9e−j2π0.3 和 0.9ej2π0.3 处有一对复极点的简单滤波器为 zer -0.5; pol 0.9*exp(j*2*pi*[-0.3 0.3]); 要查看该滤波器的零极点图&#xff0c;您可以使用 z…

Simulia仿真之CST的使用指南(1) | 百世慧®

前言 CST是Computer Simulation Technology的缩写,是全球范围内众多工程师都喜欢使用的高端电磁仿真分析软件。 本文又名《智慧的CST生活》这里一共列出了120个章节&#xff0c;其中包括CST使用过程中的有用小技巧&#xff0c;还有给用户提供技术支持的过程中常见的问题。本专…

金蝶云星空表单插件实现父窗体打开子窗体,并携带参数到子窗体

文章目录 金蝶云星空表单插件实现父窗体打开子窗体&#xff0c;并携带参数到子窗体父窗体打开子窗体准备设置携带参数打开子窗体子窗体接收参数 金蝶云星空表单插件实现父窗体打开子窗体&#xff0c;并携带参数到子窗体 父窗体打开子窗体准备 BillShowParameter OtherInAdd n…

TDD、BDD、ATDD以及SBE的概念和区别

在软件开发或是软件测试中会遇到以下这些词&#xff1a;TDD 、BDD 、ATDD以及SBE&#xff0c;这些词代表什么意思呢&#xff1f; 它们之间有什么关系吗&#xff1f; TDD 、BDD 、ATDD以及SBE的基本概念 TDD&#xff1a;&#xff08;Test Driven Development&#xff09;是一种…

Git 入门使用

一、Git 入门 1.1 Git简介 Git是一个开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理任何或小或大的项目。Git是由Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。 Git是目前世界上最先进的分布式版本控制系统&#xff0c;没有之一&a…

Visual Studio导入Wiinform项目文件,引用显示黄色感叹号

参考博客 第一步&#xff1a; 开程序包管理控制台 vs->工具->NuGet包管理器->程序包管理控制台 Update-Package –reinstall 第二步&#xff1a; 删除.csproj 文件片段 // 整个模块全部删除 包括标签中所含有的任何内容 <Target Name"EnsureNuGetPackage…