JVM系列之:再谈java中的safepoint
safepoint是什么
java程序里面有很多很多的java线程,每个java线程又有自己的stack,并且共享了heap。这些线程一直运行呀运行,不断对stack和heap进行操作。
这个时候如果JVM需要对stack和heap做一些操作该怎么办呢?
比如JVM要进行GC操作,或者要做heap dump等等,这时候如果线程都在对stack或者heap进行修改,那么将不是一个稳定的状态。GC直接在这种情况下操作stack或者heap,会导致线程的异常。
怎么处理呢?
这个时候safepoint就出场了。
safepoint就是一个安全点,所有的线程执行到安全点的时候就会去检查是否需要执行safepoint操作,如果需要执行,那么所有的线程都将会等待,直到所有的线程进入safepoint。
然后JVM执行相应的操作之后,所有的线程再恢复执行。
safepoint的例子
我们举个例子,一般safepoint比如容易出现在循环遍历的情况,还是使用我们之前做null测试用的例子:
public class TestNull {
public static void main(String[] args) throws InterruptedException {
List<String> list= new ArrayList();
list.add("www.flydean.com");
for (int i = 0; i < 10000; i++)
{
testMethod(list);
}
Thread.sleep(1000);
}
private static void testMethod(List<String> list)
{
list.get(0);
}}
运行结果如下:
标红的就是传说中的safepoint。
线程什么时候会进入safepoint
那么线程什么时候会进入safepoint呢?
一般来说,如果线程在竞争锁被阻塞,IO被阻塞,或者在等待获得监视器锁状态时,线程就处于safepoint状态。
如果线程再执行JNI代码的哪一个时刻,java线程也处于safepoint状态。因为java线程在执行本地代码之前,需要保存堆栈的状态,让后再移交给native方法。
如果java的字节码正在执行,那么我们不能判断该线程是不是在safepint上。
safepoint是怎么工作的
如果你使用的是hotspot JVM,那么这个safepoint是一个全局的safepoint,也就是说执行Safepoint需要暂停所有的线程。
如果你使用的是Zing,那么可以在线程级别使用safepoint。
我们可以看到生成的汇编语言中safepoint其实是一个test命令。
test指向的是一个特殊的内存页面地址,当JVM需要所有的线程都执行到safepint的时候,就会对该页面做一个标记。从而通知所有的线程。
我们再用一张图来详细说明:
thread1在收到设置safepoint之前是一直执行的,在收到信号之后还会执行一段时间,然后到达Safepint暂停执行。
thread2先执行了一段时间,然后因为CPU被抢夺,空闲了一段时间,在这段时间里面,thread2收到了设置safepoint的信号,然后thread2获得执行权力,接着继续执行,最后到达safepoint。
thread3是一个native方法,将会一直执行,知道safepoint结束。
thread4也是一个native方法,它和thread3的区别就在于,thread4在safepoint开始和结束之间结束了,需要将控制器转交给普通的java线程,因为这个时候JVM在执行Safepoint的操作,所以任然需要暂停执行。
在HotSpot VM中,你可以在汇编语言中看到safepoint的两种形式:'{poll}’ 或者 ‘{poll return}’ 。
总结
本文详细的讲解了JVM中Safepoint的作用,希望大家能够喜欢。
更多精彩内容
1 |
JVM系列之:从汇编角度分析NullCheck |
---|---|
2 |
JVM系列之:从汇编角度分析Volatile |
3 |
JVM系列之:JIT中的Virtual Call接口 |
作者小F,金融科技从业多年,懂技术又懂金融,主攻Java和区块链方向,篇篇都是用心之作,笔耕不辍,持续更新!
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(30)-本地化(多语言)
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(29)-T4模版
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(28)-系统小结
- 用谷歌浏览器来当手机模拟器
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(27)-权限管理系统-分配用户给角色
- ASP.NET MVC5+EF6+EasyUI 后台管理系统-分配角色给用户
- 体验vs11 Beta
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(25)-权限管理系统-系统管理员(附生成器)
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(24)-权限管理系统-将权限授权给角色
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(23)-权限管理系统-角色组模块
- jQuery Gallery Plugin在Asp.Net中使用
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(22)-权限管理系统-模块导航制作
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(20)-权限管理系统-根据权限获取菜单
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(19)-权限管理系统-用户登录
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 《Java从入门到失业》第三章:基础语法及基本程序结构(3.2-3.5):标识符、关键字、注释、变量及常量
- 《Java从入门到失业》第三章:基础语法及基本程序结构(3.1):一个简单的例子
- 详解Java解析XML的四种方法
- 《Java从入门到失业》第四章:类和对象(4.6):类路径
- 《Java从入门到失业》第四章:类和对象(4.5):包
- 《Java从入门到失业》第四章:类和对象(4.4):方法参数及传递
- 《Java从入门到失业》第四章:类和对象(4.3):一个完整的例子带你深入类和对象
- 《Java从入门到失业》第四章:类和对象(4.2):String类
- 《Java从入门到失业》第三章:基础语法及基本程序结构(3.9):数组(数组基本使用、数组的循环、数组拷贝、数组排序、多维数组)
- Establishing SSL connection without server identity verification is not recommended
- 《Java从入门到失业》第三章:基础语法及基本程序结构(3.8):流程控制(循环语句、while语句、for语句)
- 《Java从入门到失业》第三章:基础语法及基本程序结构(3.8):流程控制(选择语句、if-else语句、switch语句)
- 线上服务启动卡死,堆栈分析
- 《Java从入门到失业》第三章:基础语法及基本程序结构(3.7):运算符(自增自减、关系运算、逻辑运算、条件运算、位运算、赋值运算、类型转换)
- JavaWeb——MyBatis框架之多表查询操作实战案例总结(MyBatis1对1查询,MyBatis1对多查询,MyBatis多对多查询)