判断对象是否存活算法

引用计数算法

  • 对象每当被引用一次在其头部计数器加一,引用失效,头部减一,计数器为0时代表该对象没有任何引用,视为垃圾。
  • 缺点:无法解决循环引用问题。

可达性分析(java使用)

  • 通过GC Roots沿引用开始搜索,没有被扫描到的即视为垃圾。
  • GC时常说的标记过程就是应用可达性分析算法进行标记;注,标记标记到的都是存活的对象。

java中的GC Roots

  1. 虚拟机栈中的引用的对象
  2. 常量池中的引用(jdk7及以前中的String对象全部分配在StringPool中,jdk8开始的StringPool可能是一个指向堆中String对象的引用)。
  3. 本地方法栈中使用的对象
  4. 虚拟机内部的引用,如基本数据类型的class对象,常驻的异常对象,系统类加载器等。
  5. 被synchronize持有的对象
  6. jvm内部信息的一些对象
  7. 分区收集时,其他区的引用。(如:G1中对一个Region收集时,其他Region的引用)

并发下的可达性分析

  • gc与用户线程并发会产生的问题(如:a->b->c):

产生的问题

并发问题一

  1. c扫描结束
  2. c对象被gc标记为存活对象
  3. b->c被用户线程取消(gc不知道)
  4. gc清理垃圾(c没有被清理掉,浮动垃圾)

并发问题二

  1. a扫描结束,b扫描中
  2. b->c被用户线程取消(正在扫描b,gc知道),c被标记为垃圾
  3. a->c建立引用关系(gc不知道)
  4. gc清理垃圾(c被清理)

解决方案

增量更新

a到c建立引用关系时,a会被标记为需要被重新扫描的状态,并发标记后,以a为根,重新扫描一次。不能处理并发问题一。应用:CMS收集器

原始快照

b到c断开引用关系时,b会被标记为需要被重新扫描的状态,以b为根重新按照扫描前的快照重新扫描,当扫描到c时,借助OopMap记录能够判断c被引用,将c标记为存活对象。应用:G1收集器

猜你喜欢

转载自blog.csdn.net/liha12138/article/details/106674681