用空间换时间 —— Java虚拟机的算法实现

原创 2017年08月13日 16:36:46

带着问题阅读

  • 垃圾回收时,需不需要暂停掉除GC线程外的其他线程?
  • 内存那么大,HotSpot如何快速地找到对象?


导语

上一讲介绍了虚拟机是如何利用可达性算法,判断一个对象是否需要回收,而HotSpot在实现这个算法时,必须对算法的执行效率有严格的要求,才能保证虚拟机的高效运行,那么,HotSpot是如何实现的呢?

本文是Effective Java专栏Java虚拟机专题的第五讲,如果你觉得看完之后对你有所帮助,欢迎订阅本专栏,也欢迎您将本专栏分享给你身边的工程师同学。

在学习本节课程之前,建议您了解一下以下知识点:


快速找出GC Roots

可达性分析算法需要先找到GC Roots(什么是GC Roots),而如何在那么大的内存中找到适合当GC Roots的对象呢?如果每次GC都需要遍历全部内存,必然会消耗很多时间。

而要知道,在GC期间,GC线程以外的其他线程必须被冻结,不可以出现GC过程对象引用关系还在不断发生变化的情况,因此在GC进行时,必须暂停所有的Java执行线程(Sun称之为“Stop The World”)。所以,虚拟机必须尽量的优化GC过程的效率,减少暂停的时间。那么对于GC Roots,HotSpot是如何快速确定的呢?

这时候,准确式GC的作用就体现出来了,它采用一组称为OopMap的数据结构,来保存对象引用的位置,因此在GC时,虚拟机不必在茫茫内存大海中查找引用,只需要拿着OopMap这本字典,就可以快速地查找到所有的引用,并确定GC Roots了(典型的用空间换时间的做法)。



安全点

通过OopMap,HotSpot可以很快完成GC Roots的查找,但是,如果在每一行代码都有可能发生GC,那么也就意味着得为每一行代码的指令都生成OopMap,这样将占用大量的空间。实际上,HotSpot也不会这么做。

HotSpot只在特定的位置记录了OopMap,这些位置就叫做安全点(Safepoint),也就是说,程序并非在任意地方都可以停下了进行GC,只有到达了安全点之后才能进行。安全点一般在这些指令上产生:方法调用、循环跳转、异常跳转等。

当GC发生时,虚拟机会将中断标志设置为true,各个线程在执行时,到达安全点后,就会主动去轮询这个标志,发现中断标志为true时,就主动中断挂起;否则,则继续执行。


安全区域

前面提到的安全点,是在线程正常执行的前提才才有效的,假如线程处于sleep或者blocked状态,就无法走到安全点去中断挂起,而JVM显然不可能等待线程恢复正常,这个时候,就需要安全区域(Safe Region)来解决。

安全区域是指在一段代码片段内,引用关系不会发生变化,在这段区域内,任意地方开始GC都是安全的

当线程进入Safe Region时,首先标识自己已经进入Safe Region,这样,当HotSpot发起GC时,就不需要管这些安全区域内的线程了;当线程要离开Safe Region时,会检查系统是否已经完成了GC(有些垃圾回收器可能只需要检查是否完成了GC Roots查找),如果完成,则线程继续进行,否则就继续等待,直到受到可以安全离开Safe Region的信号。


总结

这一讲介绍了HotSpot在实现可达性分析算法时的算法,讲解了OopMap、安全点和安全区域等概念,通过这两讲的讲解,你已经知道了,垃圾回收是如何发起的,那么发起之后,又是如何回收的呢?这是接下来要讲的内容。


上一节课后思考题的答案

上一讲的问题是——“GC开始后,是否需要暂停除GC线程以外的其他线程?为什么?

答案在本讲中已经提到了,在GC期间,GC线程以外的其他线程必须被冻结,不可以出现GC过程对象引用关系还在不断发生变化的情况,因此在GC进行时,必须暂停所有的Java执行线程(Sun称之为“Stop The World”)

试想一下,假如GC期间其他线程不暂停,那么对于这两行代码:

obj = null;

obj = new Object();

obj.dosomething();

假如在代码执行到第一行时,GC线程进行了标记,将obj标记为需要回收,然而此时其他线程没有暂中断,继续执行第二行代码,执行完之后,GC遍历待回收的对象,将obj回收,接下来要发生的事情想必大家都很熟悉了——NullPointerException.


参考资料

  • 《深入理解Java虚拟机》 周志明


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

app后端开发系列文章目录

每一个程序员心中,都有一个大牛梦。我们在晨曦之光中敲击着代码,在寒冬覆雪中思考着0与1。夏练三伏 冬练三九这说的就是我们这群【江湖】中人。在这里我们门派林立,C语言派历史悠久,在江湖中就是嵩山少林,他...

swagger环境的搭建(swagger-editor|swagger-ui)

swagger环境的搭建swagger-editor、swagger-ui

Swagger使用及Springfox+SpringBoot解决404问题

Swagger简介及使用概要说明THE WORLD’S MOST POPULAR API FRAMEWORK Swagger is a powerful open source framework...
  • saum
  • saum
  • 2016-12-18 16:03
  • 5448

Swagger UI 使用

简介,基于Swagger UI其实是纯static的web程序,仅仅在页面加载的时候,调用http连接,获取yaml字符串或者json字符串,这里我将yaml文件和放到静态项目中,并使用tomcat启...

app后端开发三:laravel中使用百度的消息推送

介绍在进行APP开发过程中,会经常用到消息推送。对于创业型的公司如果自己去搭建消息推送服务器,时间成本,以及技术难度无疑都会增加很多。在我自己的实践过程中,觉得百度的消息推送服务稳定性整体来说是很高的...

35.app后端搜索入门

在app中,最常见的搜索情景就是搜索用户。只有几百,几千的用户量时,可以直接用用like这样的模糊查询,但是,如果数据有几百万,甚至上千万的时候,一次like查询数据库就堵了。到了一定量级的时候,不得...

JavDroider的作品展示

今天以一篇个人作品介绍来重新开启我的博客

Elasticsearch JDBC的使用-MySQL 数据源导入和增量索引、更新

在使用 Elasticsearch 的时候,经常会涉及到要将其它数据源的数据导入到 Elasticsearch 中,今天就来介绍一下关于 Elasticsearch 从 MySQL 导入数据和增量索引...
  • jam00
  • jam00
  • 2016-11-01 15:22
  • 5632
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)