回收对象和方法区

  • 回收对象,判断对象是否是可回收的

引用计算算法:给对象添加一个引用计数器,每当有一个地方引用它时,计数器的值就加1;当引用失效时就减1;任何时刻计数器为0的对象就是不可能再被使用的。但是大部分主流的Java虚拟机里面没有选用引用计算算法来管理内存,其中最主要的原因是它很难解决对象之间相互循环的问题。

可达性分析算法:通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走的路径称为引用链,当一个对象到“GC Roots”没有任何引用链相连时,则证明此对象是不可用的。

在Java语言中,可作为GC Roots的对象包括下面几种:

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

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

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

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

 

无论是通过引用计数算法判断对象的引用数量,还是通过可达性分析算法判断对象的引用链是否可达,判断对象是否存活都与“引用”有关。Java中引用分为4种:

  1. 强引用 在程序代码之中普遍存在的,类似“Object obj = new Object()”这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。
  2. 软引用 用来描述一些还有用但并非必须的对象。
  3. 弱引用 也用来描述一些还有用但并非必须的对象,强度比软引用更弱一些。
  4. 虚引用 也称为幽灵引用或幻影引用,它是最弱的一种引用关系。

 

即使在可达性分析算法中不可达的对象,也并非是一定会被回收的,这时候它们暂时处于“准备”被回收的状态,要真正回收一个对象,至少要经历两次标记过程:

  1. 如果对象在可达性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”。
  2. 如果这个对象被判定为有必要执行finalize()方法,那么这个对象将会放置在F-Queue的队列中,并在稍后有一个虚拟机自动创建的、低优先级的Finalizer线程去执行它。这里的执行,是指虚拟机会触发这个方法,但并不承诺会等待它运行结束。finalize()方法是对象避免被回收的方法,如果在finalize()中重新与引用链上的任何一个对象建立关联即可,这样在第二次标记时它将被移出“即将回收”的集合。注意:任何一个对象的finalize()方法都只会被系统自动调用一次。

 

  • 回收方法区

永久代的垃圾收集的主要回收两部分内容:废弃常量和无用的类。(永久代是Hotspot虚拟机特有的概念,是方法区的一种实现)

1.判断一个常量是否是“废弃常量”:没有任何对象引用常量池中的常量。

2.判断一个类是否是无用类:

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

2)加载该类的ClssLoader已经被回收。

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

                                         

                                            摘抄自《深入理解Java虚拟机:JVM高级特性与最佳实践》(第二版) 周志明著

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值