JVM-GC笔记(一)--- 什么对象需要回收

JVM对对象进行回收的前提是必须知道哪些对象是无效的,需要被回收的。
显而易见的是,需要被回收的对象就是那些已经无法访问的对象,即引用被解除的对象。

一:引用计数法
当一个对象和一个引用关联时,此对象的引用计数递增;当此引用和对象的关联被解除时,此对象的引用计数递减。
当对象的引用计数为0时,此对象不可用,被视作可回收。
但是引用计数法有一个问题就是,无法处理循环引用,如下:
A.instance = B; B.instance = A;
但是别的任何地方都不可以访问到A,B两个对象,因为A.B互相持有对方,引用计数为1,则导致A,B都不可释放,被回收。


二:可达性分析算法(JVM采用的方式)
从GC Roots开始递归向下查询引用,如果没有任何引用链可以抵挡此对象,此对象被视作可回收,GC Roots分别有以下几种:
1,虚拟机栈中引用的对象,如: Object A = new Object(); 此处A可作为Root
2,方法区中类静态属性对象,即static的属性对象
3,方法区常量引用的对象
4,本地方法栈中JNI引用的对象


HotSpot 可达性分析实现
首先要找出所有GC Roots,那么根据上文所说的,我们必须知道当前虚拟机栈中的引用的对象,需要遍历方法区找出所有的静态属性和常量等。
HotSpot通过一种oopMap的数据结构在类加载的时候计算出对象内每个位置是什么数据类型来保存执行到当前指令时有那些GC Root。
通过获取oopMap中的数据,GC可以快速枚举GC Roots, 再获取到GC Roots后,分析引用链,判断哪些对象不可达即可。

使用oopMap的问题是:如上文所述,则必须每条指令处都需要一个oopMap数据结构(至少对GC Roots有影响的指令需要),那么此方法的空间成本非常高。
解决办法:仅在特定的位置产生oopMap 如方法调用,循环开始等
如此,当运行到有oopMap的指令时,JVM就可以开始GC了。 这样的点称为[b]安全点[/b]。

新的问题:多线程时,如果线程A到了安全点,而线程B没到安全点。线程B到安全点了,线程A却没到,如此反复,永远都不可能达到GC的条件。
解决办法:当需要GC时,设置一个GC标志, 当线程运行到安全点时,判断GC标志,如果为真,则挂起自身,等待GC完成


新的问题:如果某一个线程长时间内不执行,那么会长时间内都不可到达安全点。比如sleep,获取读取大文件阻塞了。
解决办法:如果在一段代码片段中,引用关系都不会发生变化,则在此代码片段期间GC是安全的,此区间称为安全区域
当线程执行到安全区域时,标识自己进入安全区域,当JVM需要进行GC时,就不用理睬这些线程。当这些线程要离开安全区域时,就需要检查GC是否完成
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值