Java中强,软,弱,虚四种引用

Java中强,软,弱,虚四种引用

总结一下java中各种引用的用法。测试时使用-Xmx1m参数设置jvm堆大小为1mb方便模拟内存不足的情况。

一.强引用

就是直接用=等号关联的对象,只要有关联垃圾回收器不会回收。

	  //-Xmx1m设置jvm堆大小为1mb
	 public static void main(String[] args) {
     
		String s=new String("强引用");
		System.out.println("gc before"+s);
		try{
     
			byte[] b=new byte[1024*1024];
		}catch(OutOfMemoryError e) {
     
			System.out.println("OutOfMemoryError");
		}
		System.out.println("gc after"+s);
	}
	打印:
	gc before强引用
	OutOfMemoryError
	gc after强引用

可以发现发生内存溢出异常也不会回收强引用对象。

二.软引用

SoftReference引用的对象当内存不足时,如果发现堆中的对象只通过软引用关联会进行回收。

 public static void main(String[] args) throws Exception {
     
		
		SoftReference<String> sr=new SoftReference<String>(new String("软引用"));
		
		System.out.println("1"+sr.get());
		System.gc();
		System.out.println("2"+sr.get());
		try{
     
			byte[] b=new byte[1024*1000];

		}catch(OutOfMemoryError e) {
     
			System.out.println("OutOfMemoryError");
		}
		System.out.println("3"+sr.get());
	 }
	打印:
	1软引用
	2软引用
	OutOfMemoryError
	3null	 
		

注意gc后软引用内的referent字段也是null,通常我们可以使用软引用做缓存。

三.弱引用

只要触发gc,如果堆中的对象只通过弱引用关联就会进行回收。

	 public static void main(String[] args) throws Exception {
     
		
		WeakReference<String> sr=new WeakReference<String>(new String("弱引用"));
		
		System.out.println("1"+sr.get());
		System.gc();
		System.out.println("2"+sr.get());
		
	 }
	打印:
	1弱引用
	2null

注意gc后弱引用内的referent字段也是null。
弱引用适合用来的场景我感觉是当一个对象被多个地方使用时用一个强引用和几个弱引用关联它,我们不用时直接将强引用=null,它就会被回收。(这要大家自己理解一下,可以参考threadlocal的处理)

四.虚引用

虚引用与其他几种引用都不同,无法通过虚引用的常规方法获取相应的对象,虚引用主要用来跟踪对象将要被垃圾回收器回收的动作。

	 public static void main(String[] args) throws Exception {
     
		ReferenceQueue<String> rq=new ReferenceQueue<String>();
		PhantomReference<String> sr=new PhantomReference<String>(new String("虚引用"), rq);
		System.out.println("1"+sr.get());
		System.out.println("2"+rq.poll());	
		System.gc();
		Reference r=null;
		while(true) {
     
			r=rq.poll();
			if(r!=null)
				System.out.println("3"+r.get());
		}
		
	 }
	 1null
     2null
	 3null
	 结果都是null,说明无法通过虚引用的常规方法获取相应的对象。
	 但是可以通过反射获取
	 Field rereferent = Reference.class.getDeclaredField("referent");
     rereferent.setAccessible(true);
     Object result = rereferent.get(sr);
     也就是说gc其实会将虚引用对象放入队列中,但是没有真正的销毁。因为虚引用内的referent字段还指向它这点和其他引用不同,要将虚引用指向null才完全销毁它。

你可能感兴趣的:(java,java)