垃圾回收的方法(详细)

内存自动回收

程序计数器、虚拟机栈、本地方法栈3个区域随线程而生,随线程而灭;栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的(尽管在运行期会由JIT编译器进行一些优化,但在本章基于概念模型的讨论

中,大体上可以认为是编译期可知的),因此这几个区域的内存分配和回收都具备确定性,在这几个区域内就不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟随着回收了。

垃圾收集器回收:

我们只有在程序处于运行期间时才能知道会创建哪些对象,这部分内存的分配和回

收都是动态的,垃圾收集器所关注的是这部分内存,

一.如何判断对象已死

1.引用计数法

给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。,但是很难解决对象之间相互引用的问题,A.instance=b,b.instacnce=A,他两的计数器都不为0 ,但实际上着两个对象不能在被访问,但是它们也无法被垃圾回收

2.可达性分析法

过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(ReferenceChain),当一个对象到GC Roots没有任何引用链相连,也就是不可达,说明这个对象不可用,这样即使对象相互引用,但是只要不可达,就可以被判定为被回收对象

可作为GC Roots的对象包括下面几种:

虚拟机栈(栈帧中的本地变量表)中引用的对象。

方法区中类静态属性引用的对象。

方法区中常量引用的对象。

本地方法栈中JNI(即一般说的Native方法)引用的对象。

生存还是死亡:

即使在可达性分析算法中不可达的对象,也并非是“非死不可”的,这时候它们暂时处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历两次标记过程:如果对象在进行可达性分析后发现没有与GCRoots相连接的引用链,那它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法(该方法是Object下的方法,子类可以覆盖该方法实现对象整理),或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”。就会真的回收

如果这个对象被判定为有必要执行finalize()方法,则会被放入一个队列中,会有虚拟机自动建立的一个低优先级的线程去执行。这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束,这样做的原因是,如果一个对象在finalize()方法中执行缓慢,或者发生了死循环(更极端的情况),将很可能会导致F-Queue队列中其他对象永久处于等待,甚至导致整个内存回收系统崩溃。finalize()方法是对象逃脱死亡命运的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果对象要在finalize()中成功拯救自己——只要重新与引用链上的任何一个对象建立关联即可,譬如把自己(this关键字)赋值给某个类变量或者对象的成员变量,那在第二次标记时它将被移除出“即将回收”的集合;如果对象这时候还没有逃脱,那基本上它就真的被回收了

这是因为任何一个对象的finalize()方法都只会被系统自动调用一次

是Java刚诞生时为了使C/C++程序员更容易接受它所做出的一个妥协。它的运行代价高昂,

不确定性大,无法保证各个对象的调用顺序

finalize()能做的所有工作,使用try-finally或者其他方式都可以做得更好、更及时

总结:

没有引用连会进行第一次标记,看是否执行finalize方法(对象没有覆盖或者说已经执行过一次就没有必要执行该方法,会真的被回收),能执行的对象会放入一个队列,虚拟机会创建一个线程去执行(只是触发这个方法,不会等待结束,万一有一个对象执行缓慢或者 ,死循环后面的对象将一直等待),GC会对队列中的对象进行第二次标记,在第二次标记之前,拯救了自己(和引用链上的任何一个对象建立关联,把自己赋给某个类或者对象的成员变量),被移除出待回收的集合,他就不会被回收了,如果这次还没有逃脱,就真的被回收了

二.再谈引用

强引用:代码之中普遍存在的,一般用 new,只要强引用还存在,对象就一定不会被回收

软引用:描述还有用但非必须的对象,在系统发生内存溢出之前,会将这些对象回收,进行第二次回收,如果回收还没有足够内存,才抛出内存溢出异常

弱引用:也是用来描述非必需对象的,但是它的强度比软引用更弱一些,只活到下一次垃圾回收之前,一定会被回收

虚引用:最弱的,一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知

三.回收方法区

废弃常量和无用的类

类需要同时满足下面3个条件才能算是“无用的类”:

1.该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例。

2.加载该类的ClassLoader已经被回收。

3.该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

参考 深入理解java虚拟机

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值