当我们的程序开启运行之后就,就会在我们的java堆中不断的产生新的对象,而这是需要占用我们的存储空间的,因为创建一个新的对象需要分配对应的内存空间,显然我的内存空间是固定有限的,所以我们需要对没有用的对象进行回收,本文就来记录下JVM中对象的销毁过程。
1.怎么判断对象是没用的了
引用计数算法
我们在很多场景中会听到java对象判断存活的方式是计算该对象的引用计数器是否为0,如果为0就说明没有其他变量引用该对象了,这个对象就可以被垃圾收集器回收了。但事实上JVM并不是采用该算法来判断对象是否可以回收的,比如objectA.a=objectB及objectB.b=objectA除此之外没有其他引用了。但是按照引用计数算法是不会回收这两个对象的。但是这两个对象也已经不能被其他对象访问了,所以这就是问题。
可达性分析算法
java中判断对象是否可以回收是通过可达性分析算法来实现的。如下图:
在上图中object5,object6及object7这三个对象虽然有相互之间的引用,但是通过GC Roots对象并不能引用到这三个对象,所以这三个对象是满足回收条件的,而对象1到4通过GC Roots可达,所以这几个对象任然存活。
GC Roots并不是一个对象,而是一组对象,在java中可以作为GC Roots对象的有如下几种:
|序号|类型 |
|--|:--|
| 1| 虚拟机栈(本地变量表)中引用的对象 |
| 2| 方法区中类静态属性引用的对象|
| 3| 方法区中常量引用的对象|
| 4| 本地方法栈中JNI(一般说的Native方法)引用的对象|
2.对象的引用分类
判断对象是否存活我们是通过GC Roots的引用可达性来判断的,但是引用关系并不止一种,而是有四种分别是:强引用(Strong Reference),软引用(Soft Reference),弱引用(Weak Reference)和虚引用(Phantom Reference).引用强度依次减弱。
强引用
强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMmoryError错误,使程序异常终止,也不会靠随意回收具有强引用 对象来解决内存不足的问题。
软引用
软引用是用来描述一些还有用但并非必须的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。
/** * 软引用:缓存场景的使用 * @author dengp * */ public class SoftReferenceTest { /** * 运行参数 -Xmx200m -XX:+PrintGC *