Java中几种引用类型

206 阅读3分钟

    了解jvm的都知道,判断对象是否存活都与引用有关系,JDK1.2之前关于引用的描述很狭隘如果引用类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用,JDK1.2之后Java对引用的概念进行了扩充,将引用的类型分为强引用、软引用、弱引用、虚引用四种类型

强引用:代码中随处可见,只要这个引用还存在,垃圾收集器永远不会回收掉被引用的对象,jvm宁愿抛出oom

软引用:软引用的对象是包裹在SoftReference类来实现的,用来描述还有用但非必须的对象。对于软引用关联着的对象,在系统将要发生oom之前,将会把这些对象列进回收范围

弱引用:弱引用的对象是包裹在WeakReference类来实现的,用来描述非必须的对象。对于弱引用关联着的对象,当垃圾收集器工作时候,无论当前内存是否足够,都会回收掉被弱引用关联的对象

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

附上测试代码:

package reference;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

public class Test {

	//引用有哪些类型?
	//强引用:通过new创建出来的对象。只要强引用存在,垃圾回收器将不会回收。
	//软引用:通过SoftReference实现软引用,系统将要发生内存溢出之前才会对这些对象进行回收。
	//弱引用:通过WeakReference实现弱引用,无论当内存足够,GC运行时都会进行回收。
	//虚引用:通过PhantomReference实现,通过虚引用无法回去对象的实例,虚引用的作用就是当此对象被回收时,会收到一个系统通知。

	//要进行垃圾回收,如何判断一个对象是否应该被回收?
	//1、引用计数算法:每当有一个地方引用他,就加1,引用失效,就减1.数量为0,说明可以进行回收。引用计数算法的缺点就是无法判断两个对象之间存在相互引用的情况。jvm中没有使用这种判断方式。
	//2、可达性分析算法:jvm中使用的时这种方式,通过一系列GCRoot对象作为起始点,从这些点开始向下搜索,搜索的路径成为引用链,当一个对象到GC没有任何引用链,说明对象可以被回收。

	//上面提到GCRoot,那GCRoot对象有哪些?
	//(1)虚拟机栈的栈帧中引用的对象。
	//(2)方法区中静态属性引用的对象。
	//(3)方法区中常亮引用的对象。
	//(4)本地方法栈中引用的对象。

	public static void main(String[] args) throws InterruptedException {
		// 只要obj还指向Object对象,Object对象就不会被回收
		Object obj = new Object(); 
		System.gc();
		System.out.println("强引用关联的对象:"+obj);
		System.out.println("---------------------------------");

		// 发生oom异常前才会回收
		Object obje = new Object();
		SoftReference<Object> softReference = new SoftReference<Object>(obje);
		obje = null;
		// 即使触发回收了,因为内存足够也不会对软引用关联的对象进行回收
		System.gc();
		Thread.sleep(1000);
		System.out.println("软引用关联的对象"+softReference.get());
		System.out.println("---------------------------------");

		// 触发gc时候会回收
		Object objec = new Object();
		WeakReference<Object> weakReference = new WeakReference<Object>(objec);
		objec = null;
		// 如果触发回收就会对弱引用关联的对象进行回收
		System.gc();
		System.out.println("弱引用关联的对象:"+weakReference.get());
		System.out.println("----------------------------------");

		// 跟踪一个对象什么时候被回收
		Object o = new Object();
		// 引用队列
		ReferenceQueue queue = new ReferenceQueue();
		PhantomReference p = new PhantomReference(o,queue);
		o = null;
		System.out.println("虚引用关联的对象:"+p.get());
		System.gc();
		Thread.sleep(1000);
		System.out.println("虚引用:"+queue.poll());
	}

}