小师妹学JVM之:JVM中的Safepoints
简介
java程序员都听说过GC,大家也都知道GC的目的是扫描堆空间,然后将那些标记为删除的对象从堆空间释放,以提升可用的堆空间。今天我们会来探讨一下隐藏在GC背后的一个小秘密Safepoints。
GC的垃圾回收器
小师妹:F师兄,GC的垃圾回收器的种类为什么会有这么多呀?使用起来不是很麻烦。并且我听说CMS在JDK9zhong已经被废弃了。
小师妹,这么多垃圾回收器实际是在JVM的发展过程中建立起来的,在之前的文章中,我们讲到了目前的GC回收器有这样几种。
- 基于分代技术的回收器
Concurrent mark sweep (CMS) ,CMS是mark and swap的升级版本,它使用多个线程来对heap区域进行扫描,从而提升效率。
由于CMS的参数复杂性和性能问题,CMS已经在JDK9中被废弃了。
Serial garbage collection,使用单一的线程来进行垃圾回收操作,其好处就是不需要和其他的线程进行交互。如果你是单核的CPU,那么最好就是选择Serial garbage collection,因为你不能充分利用多核的好处。同样的它也常常用在比较小型的项目中。
Parallel garbage collection,如果你是多核处理器,那么Parallel GC可能是你的选择。
Parallel GC是JDK8中的默认GC。而在JDK9之后, G1是默认的GC。
G1 garbage collection,G1=Garbage First,它是为替换CMS而生的,最早出现在java7中。
G1将heap区域划分成为多个更小的区域,每个小区域都被标记成为young generation 或者old generation。从而运行GC在更小的范围里运行,而不是影响整个heap区域。
- 非基于分代技术的回收器
Z Garbage Collection,ZGC是一个可扩展的,低延迟的GC。ZGC是并发的,而且不需要停止正在运行的线程。
ZGC是在JDK11中引入的。
当然还有正在研发中的其他GC。
分代回收器中的问题
小师妹:F师兄,分代回收器不好吗?为什么还有新的ZGC等基于非分代技术的回收器?
分代垃圾回收器中有一个非常常见的现象就是"Stop The World"。什么是Stop the world呢?
就是说在GC的时候,为了进行垃圾回收,需要所有的线程都要暂停执行。所有的线程都暂停执行。
当然G1虽然是基于分代技术,但是G1实际上是不会"Stop The World"的。
JVM定义了一些Root对象,从这些对象开始,找出他们引用的对象,组成一个对象图。所有在这个图里面的对象都是有效的对象,反之不在对象图中的对象就应该被回收。有效的对象将会被Mark为alive。
这些Root对象包括:正在执行的方法中的本地对象和输入参数。活动的线程,加载类中的static字段和JNI引用。
safepoints
为了实现STW的功能,JVM需要提供一个机制,让所有的线程可以在某一个时刻同时停下来。这个停下来的时刻就叫做safepoints。
注意,这些停下来的线程不包括运行native code的线程。因为这些线程是不属于JVM管理的。
JVM中的代码执行其实有两种方式,一种是JIT编译成为机器码,一种是解释执行。
在JIT中,直接将检查代码编译进入了机器码中。通过设置相应的标记位,从而在线程运行的过程中执行暂停的指令。
还是举一个上篇文章中我们提到的JMH的例子:
@Benchmark
    public void test1() {
        int length = array.length;
        for (int i = 0; i < length; i=i+1)
            array[i] ++;
    }
我们看一下它的assembly code:

可以看到其中有个test的指令,这个test指令就是生成的safe points。
通过设置标志位,就可以在线程运行时执行暂停操作。
如果是解释执行的话,JVM保存了两个字节码的调度table,当需要safepoint的时候,JVM就进行table的切换,从而开启safepoint。
safepoint一般用在什么地方
一般情况下,GC,JIT的反代码优化,刷新code cache,类重定义 ,偏向锁撤销和其他的一些debug操作。
我们可以通过使用-XX:+PrintGCApplicationStoppedTime来print safepints的暂停时间。
-XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1这两个参数可以强制JVM打印safepoint的一些统计信息。
总结
Safepoint是垃圾回收中一个非常重要的概念,希望大家能够有所了解。
本文作者:flydean程序那些事
本文链接:http://www.flydean.com/jvm-jit-safepoints/
本文来源:flydean的博客
欢迎关注我的公众号:程序那些事,更多精彩等着您!
小师妹学JVM之:JVM中的Safepoints的更多相关文章
- 小师妹学JavaIO之:NIO中那些奇怪的Buffer
		目录 简介 Buffer的分类 Big Endian 和 Little Endian aligned内存对齐 总结 简介 妖魔鬼怪快快显形,今天F师兄帮助小师妹来斩妖除魔啦,什么BufferB,Buf ... 
- 小师妹学JavaIO之:NIO中Channel的妙用
		目录 简介 Channel的分类 FileChannel Selector和Channel DatagramChannel SocketChannel ServerSocketChannel Asyn ... 
- 小师妹学JVM之:深入理解JIT和编译优化-你看不懂系列
		目录 简介 JIT编译器 Tiered Compilation分层编译 OSR(On-Stack Replacement) Deoptimization 常见的编译优化举例 Inlining内联 Br ... 
- 小师妹学IO系列文章集合-附PDF下载
		目录 第一章 IO的本质 IO的本质 DMA和虚拟地址空间 IO的分类 IO和NIO的区别 总结 第二章 try with和它的底层原理 简介 IO关闭的问题 使用try with resource ... 
- 小师妹学JavaIO之:文件系统和WatchService
		目录 简介 监控的痛点 WatchService和文件系统 WatchSerice的使用和实现本质 总结 简介 小师妹这次遇到了监控文件变化的问题,F师兄给小师妹介绍了JDK7 nio中引入的Watc ... 
- 小师妹学JVM之:JIT中的PrintAssembly
		目录 简介 使用PrintAssembly 输出过滤 总结 简介 想不想了解JVM最最底层的运行机制?想不想从本质上理解java代码的执行过程?想不想对你的代码进行进一步的优化和性能提升? 如果你的回 ... 
- 小师妹学JVM之:JDK14中JVM的性能优化
		目录 简介 String压缩 分层编译(Tiered Compilation) Code Cache分层 新的JIT编译器Graal 前置编译 压缩对象指针 Zero-Based 压缩指针 Escap ... 
- 小师妹学JVM之:JIT中的LogCompilation
		目录 简介 LogCompilation简介 LogCompilation的使用 解析LogCompilation文件 总结 简介 我们知道在JVM中为了加快编译速度,引入了JIT即时编译的功能.那么 ... 
- 小师妹学JVM之:JIT中的PrintCompilation
		目录 简介 PrintCompilation 分析PrintCompilation的结果 总结 简介 上篇文章我们讲到了JIT中的LogCompilation,将编译的日志都收集起来,存到日志文件里面 ... 
- 小师妹学JVM之:JIT中的PrintAssembly续集
		目录 简介 JDK8和JDK14中的PrintAssembly JDK8中使用Assembly JDK14中的Assembly 在JMH中使用Assembly 总结 简介 上篇文章和小师妹一起介绍了P ... 
随机推荐
- Servlet Session MVC模式
			一 什么是Session 当首次使用session时,服务器端要创建session,session是保存在服务器端,而给客户端的session的id(一个cookie中保存了sessionId). ... 
- 痞子衡嵌入式:链接函数到8字节对齐地址或可进一步提升i.MXRT内核执行性能
			大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT上进一步提升代码执行性能的经验. 今天跟大家聊的这个话题还是跟痞子衡最近这段时间参与的一个基于i.MXRT1170的大项目有 ... 
- 04.Java基础语法
			一.Java源程序结构与编程规范 一个完整的Java源程序应该包含下列部分 package语句,至多一句,必须放在源程序第一句 import语句,没有或者若干句,必须放在所有类定义前 public c ... 
- Crypto++ AES 加密解密流程
			// aesdemo.cpp : 定义控制台应用程序的入口点. // #include <stdio.h>#include <tchar.h>#include <iost ... 
- ios swift 知识点记录
			1. 定义变量 var name = "***" 定义常量 let name ="*****" 2. swift 变量类型 String, Int, Fl ... 
- 动作函数-web_submit_data
			web_submit_data("login.pl", "Action=http://127.0.0.1:1080/WebTours/login.pl", &q ... 
- Oracle连接Db2
			因为有个业务场景需要访问客户DB2数据库的数据,我们使用的Oracle,百度一下是有方法的,本来以为很简单,没想到搞了一天,因为数据库版本都太老,使用的也少走了不少弯路,在此记录下来给需要的人借鉴. ... 
- vc6.0代码转vs2017相关问题
			vc6.0代码转vs2017相关问题 命令行 error D8016: “/ZI”和“/Gy-”命令行选项不兼容fatal error C1083: 无法打开包括文件: “WinSock2.h”: N ... 
- Java学习笔记7(IO)
			IO(输入输出) IO流按照操作数据的不同,分为字节流和字符流,按照数据传输方向分为输入流和输出流. 字节流 计算机中,所有文件都是以二进制(字节)形式存在,IO流中针对字节的输入输出提供了一系列的流 ... 
- Tensorflow 中(批量)读取数据的案列分析及TFRecord文件的打包与读取
			内容概要: 单一数据读取方式: 第一种:slice_input_producer() # 返回值可以直接通过 Session.run([images, labels])查看,且第一个参数必须放在列表中 ... 
