您的位置:首页 > 编程语言 > Java开发

3、垃圾收集之回收的对象

2017-05-07 10:34 267 查看


导读

关于垃圾收集需要做的是3件事:

- 哪些内存需要回收?

- 什么时候回收?

- 如何回收?

我们已经了解到,程序计数器、虚拟机栈、本地方法栈(忘记的话,请重新看前两篇内容)这3个区域是随着线程生灭的;这几个区域的内存分配和回收是可以确定的,在方法结束或者线程结束时,内存就跟着被回收了。

而JAVA堆和方法区不一样,它们只有在程序运行时才会动态的创建对象,动态的对内存进行分配和回收,而垃圾收集器关注的就是这部分内存。我们常说JAVA是面向对象的,而这部分内存里也是充满了一个又一个的对象。那么,垃圾收集器要根据什么条件来判断哪些对象是该回收的呢?

什么样的对象会被回收?

很明显,当一个对象不再被任何地方使用的时候,就说明它该被回收了。所以,我们要了解的其实是怎么去判断一个对象已死。判断的方法有两种:引用计数算法和可达性分析算法。而在JAVA中使用的是可达性分析算法。原因下面会说名。

引用计数算法

给对象添加一个引用计数器,每当有地方引用它,计数器就+1,引用失效时就-1;当计数器为0时就是对象不再使用的时候。

这个方法简单高效,不过在JAVA中却没有被使用。因为它很难处理对象之间互相循环引用的问题。

可达性分析算法

同一个一系列称为“GC Roots”的对象为起始点,从这些节点往下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链的时候,则证明这个对象不可用。



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

- 虚拟机栈中的引用对象;

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

- 方法区中常量引用的对象;

- 本地方法栈中JNI引用的对象。

关于引用

无论是引用计数算法还是可达性分析算法,它们判断对象是还或者都与引用有关。在Java中,引用被分为四种:强引用、软引用、弱引用、虚引用。四种引用依次逐渐减弱。

强引用:类似”Object obj=new Object()”这样的引用,只要这类引用存在,对象就不会被回收。

软引用:还有用但并非必须的对象。在系统将要发生内存溢出异常前,将会把这类对象列在回收范围内,在第二次内存回收时回收。

弱引用:也是非必须对象,比软饮用的强度还弱一些。只能生存到下一次垃圾收集之前。当垃圾收集器工作时,无论内存是否足够,都会回收掉这部分对象。

虚引用:也成为幽灵引用或幻影引用。设置虚引用的唯一目的就是能在这个对象被回收时收到一个系统通知。

然而,即使是可达性分析算法不可达的对象,也不是非死不可的。这时候,它们会执行finalize()方法,暂时处于死缓阶段;而当对象没有覆盖这个方法或者这个方法已经被执行过了,那么它就真要死了。

回收方法区

方法区的垃圾收集主要分为两部分:废弃常量和无用的类。废弃常量回收与Java堆中的对象相似;要回收无用的类,条件就比较苛刻一些了:

- 该类所有实例已经被回收,也就是java堆中不存在该类任何实例。

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

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

满足以上条件后,也仅仅只是可以被回收而不是必然被回收。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息