垃圾收集器回收对象的依据和时机

Java中的引用:算法

Java中将引用分为强引用、软引用、弱引用、虚引用4种,强度依次减弱。
强引用:Object obj = new Object(),只要强引用还存在,垃圾收集器就永远不会回收这些引用关联着的对象。
软引用:用来描述一些还有用但并不是必需的对象。
	在系统将要发生内存溢出异常前,垃圾收集器才会去回收这些软引用关联着的对象。jdk1.2以后,提供了SoftReference类来实现软引用。
弱引用:和软引用同样,也是描述一些还有用但并不是必须的对象,只是它的强度更弱一些。
	当垃圾收集器工做时,不管当前内存是否够用,都会回收掉只被弱引用关联的对象。jdk1.2以后,提供了WeakReference类来实现软引用。
虚引用:是最弱的一种引用,一个对象是否有虚引用的存在,彻底不会对其生存时间构成影响,也没法经过虚引用来取得一个对象实例。
	设置虚引用的惟一目的:在这个对象被垃圾收集器回收时获得一个系统通知。

判断对象是否存活的算法:this

1)引用计数算法:
	概念:给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1;当引用失效时,计数器就减1;当计数器为0时,对象就不能再使用了。
	说明:Java虚拟机里面没有采用 引用计数算法 来管理内存。缘由:不能解决对象之间相互循环引用的问题
	案例:
		ReferenceCountingGC{
		
			public Object instance = null;
			
			// 这个成员属性的惟一意义就是占用一些内存,以便在GC日志中能够明显地看出是否被回收过
			private byte[] bigBlock = new byte[1024 * 1024];
			
			public static void testGC() {
				ReferenceCountingGC objA = new ReferenceCountingGC();
				ReferenceCountingGC bojB = new ReferenceCountingGC();
				
				objA.instance = objB;
				objB.instance = objA;
				
				objA = null;
				objB = null;
				
				// 假设在这行发生GC,那么objA和objB是否被回收呢?
				System.gc();
			}
		}
		
		由运行结果能够看出:虚拟机并无由于这两个对象相互引用就不去回收它们。说明:虚拟机不是经过引用计数算法来判断对象是不是存活的。

2)可达性分析算法(根搜索算法):
	概念:从根节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象与根节点之间不存在任何引用链时,则证实此对象是不可用的。
	根对象的断定:
		1)虚拟机栈(栈帧中的本地变量表)中引用的对象、本地方法栈中JNI(即native方法)引用的对象。
		2)方法区中:类静态属性引用的对象、常量引用的对象。

一个对象被回收要通过两次标记:线程

第一次标记:
	若是一个对象在进行可达性分析后没有发现与根对象间存在引用链,那么这个对象将被第一次标记,并进行判断:判断此对象是否有必要去执行finalize()方法。
		1)若是:对象没有覆盖finalize()方法,或者finalize()方法已经被调用过了,虚拟机就不会执行该对象的finalize()方法,直接回收该对象。
		2)若是:对象覆盖了finalize()方法,而且finalize()方法没有被调用过,那么:
			1>这个对象将会放置在一个叫作F-Queue 的队列中,稍后(在第二次标记以前),会有一个由虚拟机自动创建的、低优先级的Finalizer线程去执行该对象的finalize()方法。				2>注意:这里的“执行”是指虚拟机会触发这个方法,可是并不保证会等待这个方法运行结束。缘由:若是某个对象执行finalize()方法花费的时间比较长,或者发生了死循环,这样的话就极可能会致使F-Queue队列中其它的对象永久等待,若是JVM要等待它运行结束,则有可能会致使整个内存回收系统崩溃。

第二次标记:
	在第一次标记后,GC将对 F-Queue 中的对象进行第二次标记,若是对象在finalize()方法中成功拯救本身,那么这个对象将被移出”即将回收“的那个集合。若是没有在finalize()方法中救出本身,那么它将被GC回收。
	注:在finalize()方法中拯救本身的方法:只要从新与引用链上的任何一个对象创建关联便可。例如:将本身(this)赋值给某个对象的成员变量。
相关文章
相关标签/搜索