上篇文章中,我们了解了Java虚拟机垃圾回收的思路和策略,这篇文章我们将了解Java是如何实现高效的回收算法的。

  我们需要了解,内存回收必须要保证“一致性”,意思就是在执行GC分析的时候,系统看起来要像是冻结在某一时间点上,不能出现在分析过程中,引用的情况还在发生变化,这样就无法进行分析,这是为什么在GC时必须要停顿所有的Java线程(官方称之为Stop The World),Java是通过引用计数器和可达性分析算法来判断一个对象是否可以被回收的,在进行可达性分析的时候,首先要枚举出所有的根结点GC-Roots,一个一个去挑选显然是不现实的,因为这会导致系统长时间的STW,而且,虚拟机是可以知道哪些地方存在存放着直接引用的,依靠使用一种叫做OOP的数据结构来达到这个目的,在类加载完成的时候,HotSpot就把对象内什么偏移量上是什么类型的数据计算出来,在JIT编译的过程中,也会在特定的位置几下栈和寄存器中哪些位置是引用,这样在GC扫描时,就可以直接获取这些信息了。

  上文也提到,并不会为每一条指令都创建OOP,因为这样会产生大量的内存消耗,得不偿失只会在特定位置创建,这个位置就是“安全点(Safe Point)”,程序只有在安全点才可以停下来执行GC,安全点设置的时候,为了追求合理(例如当需要执行GC时,不能让GC等候太久才进入安全点),这个标准就是“是否会让程序执行太久”,注意,这个判断条件不能以指令集的长度来判断,因为每条指令执行的时间都很短,其最明显的特征就是指令序列复用,例如方法跳转,循环跳转,异常跳转等,所以,具有这些功能的指令才会产生安全点。

  对于安全点,另一个需要考虑的问题是如何在GC发生时,让所有的线程都跑到最近的安全点上停下来,这里有两个方案选择:一是抢先式中断,就是在GC发生时,将所有的线程中断,如果发现有线程中断的地方不在安全点上,就恢复该线程,现在几乎没有虚拟机采用这种抢先式中断;而是主动式中断,设置一个标志,在GC发生时,该标志为真,在每个安全点上去查看这个标志,当这个标志为真时,就自己挂起中断。

  另外我们需要扩充一个安全域的概念,因为当有些线程正好处于Sleep或Block状态时,无法响应JVM的暂停请求,JVM也不可能等待CPU重新分配时间片,这就需要安全域来解决,安全域是指在一个代码片段中,引用关系不会发生变化,在这个区域中任何地方开始GC都是安全的,我们可以把安全域看作是对安全点的一个扩充。当线程执行到Safe Region时,就会标识自己已经进入SafeRegion,当需要执行GC时,不用管这种线程,当这种线程将要跳出SafeRegion时,会检查系统是否已经枚举完了根结点(或整个GC过程完成),如果没有,则必须等待到可以安全离开SafeRegion的信号为止。

  可以看出,JVM在具体的实现细节上遇到了很多问题,所以我们要深入了解JVM,学习优秀的解决方案,不能只停留在表面。

  本文我们了解了JVM在执行GC时的一些细节,下篇文章我们将会介绍几种流行的商用垃圾收集器。

最新文章

  1. 【leetcode】Kth Largest Element in an Array (middle)☆
  2. 转载 Android快捷键 转载
  3. java length size
  4. 在MongoDB中使用JOIN操作
  5. php session 自定义的设置测试
  6. 记一次lvs-tunnel模式的故障分析(7)
  7. java web(转)
  8. 第六届蓝桥杯B组java最后一题
  9. mysql8.0 Server 在Windows平台中的安装、初始化和远程访问设置
  10. project 2013 显示标题
  11. JS设计模式(14)适配器模式
  12. selenium css定位方式
  13. Multi-cloud Kubernetes with Triton
  14. Java: war包的作用及使用方法,如何解压后缀名为war的文件
  15. android免root hook框架legend
  16. Linux内核(3) - 分析内核源码如何入手(下)
  17. python-web 创建一个输入链接生成的网站
  18. WPF和Expression Blend开发实例:Adorner(装饰器)应用实例
  19. 基于Thrift的跨语言、高可用、高性能、轻量级的RPC框架
  20. 저장소system.runtime.remoting.messaging.callcontext

热门文章

  1. 后退欧拉法求解常微分方程(c++)
  2. forEach, map, filter方法区别
  3. hdoj - 2602 Bone Collector
  4. RPC接口测试(三) RPC接口测试
  5. mariadb使用with子句重写SQL性能提升5倍
  6. golang testing 无法获取覆盖率问题
  7. IDEA 开发javafx: error: java:package javafx.application does not exist
  8. Swift自定义AlertView
  9. 导入一个eclipse的java项目到IDEA报Cannot find JDK '1.7' for module 'TEST'
  10. [转]nodejs导出word