java四种引用

1.强引用

强引用指向的对象,在任何时候都不会被回收。除非将引用置为null

/**
 * 强引用 
 */
public class StrongReferences {

	public static void main(String[] args) {
		
		//创建一个对象,new出来的对象都是分配在java堆中的
        Sample sample = new Sample();   //sample这个引用就是强引用

        sample = null;                  //将这个引用指向空指针,
                                        //那么上面那个刚new来的对象就没用任何其它有效的引用指向它了
                                        //也就说该对象对于垃圾收集器是符合条件的
                                        //因此在接下来某个时间点 GC进行收集动作的时候, 该对象将会被销毁,内存被释放
		System.gc();
	}
	
}

2.软引用

软引用在java.lang.ref包中有与之对应的类java.lang.ref.SoftReference。 
重点: 被软引用指向的对象不会被垃圾收集器收集(即使该对象没有强引用指向它),除非jvm使用内存不够了,才会对这类对象进行销毁,释放内存。

/**
 * 软引用 
 * 软引用在java.lang.ref包中有与之对应的类java.lang.ref.SoftReference。 
 * 重点: 被软引用指向的对象不会被垃圾收集器收集(即使该对象没有强引用指向它),除非jvm使用内存不够了,才会对这类对象进行销毁,释放内存。
 */
public class SoftReferences {

	public static void main(String[] args) throws InterruptedException {
		
        //创建一个软引用指向这个对象,使用-Xmx10m参数,可以将堆内存分配为10M
        SoftReference<Sample> softRef = new SoftReference<Sample>(new Sample());

        //如果此时堆内存不够用了,软引用指向的对象就会被回收。
        List<Object> list = new ArrayList<Object>();
        while(true){
            /*如果重写了Sample类的finalize方法,内存不足时就可以看到
        	该方法被调用,说明Sample对象被回收*/
        	System.out.println(softRef.get());
        	list.add(new byte[1024 * 1024 * 1]);
        	Thread.sleep(1000);
        }
	}
	
}

3.弱引用

弱引用会被jvm忽略,也就说在GC进行垃圾收集的时候,如果一个对象只有弱引用指向它,那么和没有引用指向它是一样的效果,jvm都会对它就行果断的销毁,释放内存。

如果弱引用指向一个gc root可达的对象,那么该弱引用不会被回收,除非该对象变为可回收对象
其实这个特性是很有用的,jdk也提供了java.util.WeakHashMap这么一个key为弱引用的Map。比如某个资源对象你要释放(比如 db connection), 但是如果被其它map作为key强引用了,就无法被jvm收集。

/**
 * 弱引用会被jvm忽略,也就说在GC进行垃圾收集的时候,如果一个对象只有弱引用指向它,那么和没有引用指向它是一样的效果,jvm都会对它就行果断的销毁,释放内存。
 * 其实这个特性是很有用的,jdk也提供了java.util.WeakHashMap这么一个key为弱引用的Map。比如某个资源对象你要释放(比如 db connection), 但是如果
 * 被其它map作为key强引用了,就无法被jvm收集。
 */
public class WeakReferences {

	public static void main(String[] args) throws InterruptedException {
		testWeakReferences1();
		//testWeakReferences2();
	}
	
	/**
	 * 弱引用会被JVM忽略,直接回收 
	 */
	public static void testWeakReferences1(){
		WeakReference<Sample> weakRef = new WeakReference<Sample>(new Sample());
            System.out.println(weakRef.get());
            //此时只有弱引用指向sample了,sample会被回收
            System.gc();
            Thread.sleep(2000);
            //这里会返回null
            System.out.println(weakRef.get());
	}
	
	/**
	 * 弱引用Map
	 * @throws InterruptedException 
	 */
	public static void testWeakReferences2() throws InterruptedException{
		WeakReference<Sample> weakRef = new WeakReference<Sample>(new Sample());

		//此处如果使用hashMap,就算使用弱引用,GC也会认为weakRef指向的对象不可回收,不能回收该Key对象
        //Map<Sample,String> map = new HashMap<Sample, String>();
        //此处如果使用WeakHashMap,Key使用弱引用,而且WeakHashMap的Key是可以回收的,所以weakRef指向的对象会被回收
        Map<Sample,String> map = new WeakHashMap<Sample, String>();
        
        map.put(weakRef.get(),"test");

        //这里会返回test
        System.out.println(map.get(weakRef.get()));
        System.gc();
        Thread.sleep(2000);
        //这里会返回null,说明键已经被回收
        System.out.println(map.get(weakRef.get()));

        //此处使用WeakHashMap,key是一个对象,但是没有其他引用指向它
        //所以会被GC回收,map的长度会变化
        Map<Sample,String> map2 = new WeakHashMap<Sample, String>();
        map2.put(new Sample(),"test");
        //这里返回1
        System.out.println(map2.size());
        System.gc();
        Thread.sleep(2000);
        //这里返回0,说明键已经被回收
        System.out.println(map2.size());
	}
	
}

4.虚幻引用

虚幻引用和弱引用的回收机制差不多,都是可以被随时回收的。但是不同的地方是,它的构造方法必须强制传入ReferenceQueue,因为在jvm回收前(重点: 对,就是回收前,软引用和弱引用都是回收后),会将PhantomReference对象加入ReferenceQueue中; 还有一点就是PhantomReference.get()方法永远返回空,不管对象有没有被回收。

/**
 * 虚引用 
 * 虚幻引用和弱引用的回收机制差不多,都是可以被随时回收的。但是不同的地方是,它的构造方法必须强制传入ReferenceQueue,
 * 因为在jvm回收前(重点: 对,就是回收前,软引用和弱引用都是回收后),会将PhantomReference对象加入ReferenceQueue中; 
 * 还有一点就是PhantomReference.get()方法永远返回空,不管对象有没有被回收。
 */
public class PhantomReferences {
	
	private static final ReferenceQueue<Sample> QUEUE = new ReferenceQueue<>();

	public static void main(String[] args) throws InterruptedException {
		
        //创建一个虚引用指向这个对象
		Sample sample = new Sample();
		//如果重写了Sample的finalize方法,那么就不会放入引用队列中
		PhantomReference<Sample> phantomRef = new PhantomReference<Sample>(sample,QUEUE);
		sample = null;
		//永远都返回null
        System.out.println(phantomRef.get());
        
        System.gc();
        Thread.sleep(2000);
        if(QUEUE.poll()!=null){
        	System.out.println("虚引用被回收了");
        }
        
	}
	
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值