强软弱虚四大引用

1 概述

在JVM里面把引用分成四种类型,每种类型在JVM进行垃圾回收的时候又不同的操作,这四种类型非别是:
Reference:强引用
SoftReference:软引用
WeekRerence:弱引用
PhantonReference:虚引用

2 强引用

95%的情况下我们使用过的引用都是强引用

2.1 垃圾回收方式

当JVM进行垃圾回收时,遇到强引用是不会进行回收的,哪怕是发生啦OOM异常。

强引用是我们最常见的普通对象引用,只要还有强引用指向一个对象,就能表明对象还“活着”,垃圾收集器不会碰这种对象。在Java中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用。当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的,即使该对象以后永远都不会被用到JVM也不会回收。因此强引用是造成Java内存泄漏的主要原因之一。对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用赋值为null,一般认为就是可以被垃圾收集的了(当然具体回收时机还是要看垃圾收集策略)。

2 .2 代码实例

在这里插入图片描述

3 软引用

3.1 垃圾回收方式

内存足够的情况下不收,内存不足/发生OOM会回收
在这里插入图片描述

3.2 代码实例

package InterviewTest;

import java.lang.ref.SoftReference;

public class SoftRefenceDemo {
	
	
	/**
	 * 内存够用不回收
	 */
	public static void softRef_Memory_Enough() {
		Object o1 = new Object();
		SoftReference<Object> softReference = new SoftReference<Object>(o1);
		System.out.println(o1);
		System.err.println(softReference);
		
		o1=null;
		System.gc();
		
		System.out.println(o1);
		System.out.println(softReference.get());
	}
	/**
	 * 内存不够才回收
	 */
	public static void softRef_Memory_NotEnough() {
		Object o1 = new Object();
		SoftReference<Object> softReference = new SoftReference<Object>(o1);
		System.out.println(o1);
		System.err.println(softReference);
		
		o1=null;
//		System.gc();
		
		try {
			byte[] bytes = new byte[30*1024*1024];
			System.out.println(bytes);
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			System.out.println(o1);
			System.out.println(softReference.get());
		}
		System.out.println("**************");
	}
	
	
	public static void main(String[] args) {
//		softRef_Memory_Enough();
		softRef_Memory_NotEnough();
	}

}

4 弱引用

4.1 垃圾回收方式

不论内存是否足够,只要发生GC回收,都会被回收
在这里插入图片描述

4.2 代码实例

package InterviewTest;
import java.lang.ref.WeakReference;

public class WeakRefenceDemo {
	
	public static void main(String[] args) {
		Object o1 = new Object();
		WeakReference<Object> weakReference = new WeakReference<Object>(o1);
		System.out.println("o1:"+o1);
		
		o1 = null;
		System.out.println("o1:"+o1);
		System.out.println("weakReference:"+weakReference.get());
		System.gc();
		System.out.println("*******************");
		
		System.out.println("o1:"+o1);
		System.out.println("weakReference:"+weakReference.get());
	}

}

在这里插入图片描述

4.3 使用场景

在这里插入图片描述
安卓手机,前端浏览器
保证不用每次都从硬盘读取,但又要防止OOM异常

4.4 WeakHashMap

当一个key已经无效(key=null)的时候,只要发生GC,
这个键值对就会被回收,map中其他的key有效的不会被回收。

4.4.1 代码示例

package InterviewTest;
import java.util.HashMap;
import java.util.WeakHashMap;

public class WakHashMapDemo {
	
	public static void main(String[] args) {
		myHashMap();
		System.out.println("-----------------------------------");
		myWeakHashMap();
	}
	public static void myHashMap() {
		HashMap<Integer, String> map = new HashMap<>();
		Integer key = new Integer(1);
		String value = "HashMap";
		map.put(key, value);
		System.out.println(map);
		System.out.println(" ******* ");
		key = null;
		System.out.println(map);
		System.out.println(" ******* ");
		System.gc();
		System.out.println("map:"+map+" size:"+map.size());
	}
	public static void myWeakHashMap() {
		WeakHashMap<Integer, String> map = new WeakHashMap<>();
		Integer key = new Integer(2);
		String value = "HashMap";
		map.put(key, value);
		Integer key2 = new Integer(22);
		String value2 = "HashMap2";
		map.put(key2, value2);
		System.out.println(map);
		System.out.println(" ******* ");
		key = null;
		System.out.println(map);
		System.out.println(" ******* ");
		System.gc();
		System.out.println("map:"+map+" size:"+map.size());
	}
}

在这里插入图片描述

5 虚引用

5.1 回收方式

虚引用,形同虚设,不会决定对象的生命周期。

一个对象持有虚引用,那它就跟没有任何引用一样,在任何时候都能被垃圾回收器回收。他不能单独使用,也不能通过它访问对象,虚引用必须和引用队列(ReferenceQueue)联合使用。

虚引用的作用是跟踪对象被垃圾回收的状态,仅仅是提供一种确保对象被finalize以后,做某些事情的机制。

虚引用对象的get()方法返回值总是null
在这里插入图片描述

5.2 代码实例


package InterviewTest;

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


/**
 * @author admin
 *java 提供了4种引用类型,在垃圾回收的时候,都有自己各自的特点
 *ReferenceQueue是用来配额引用工作的,没有ReferenceQueue一样可以运行
 *
 *创建引用的时候可以指定关联的队列,当GC释放对象内存的时候,会将引用加入到引用队列
 *如果程序发现了某个虚引用已经加入到引用队列, 那么就可以在引用的对象内存被回收之前采取必要的行动
 *这相当于是一种通知机制
 *
 *当关联的引用队列中有数据的时候,意味着引用指向的堆内存中的对象被回收。
 *通过这种方式,JVM允许我们在对象被销毁后,做一些我们自己想做 的事情。
 *
 *
 */
public class PhantomReferenceDemo {
	public static void main(String[] args) throws InterruptedException {
		Object o1 = new Object();
		ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
		PhantomReference< Object> phantomReference = new PhantomReference<Object>(o1, referenceQueue);
		System.out.println("o1:"+o1);
		System.out.println("phantomReference:"+phantomReference.get());
		System.out.println("referenceQueue:"+referenceQueue.poll());
		
		System.out.println("****************");
		
		o1=null;
		System.gc();
		Thread.sleep(500);

		System.out.println("****************");
		System.out.println("o1:"+o1);
		System.out.println("phantomReference:"+phantomReference.get());
		System.out.println("第一次referenceQueue:"+referenceQueue.poll());
		System.out.println("第二次referenceQueue:"+referenceQueue.poll());
	}
}

5.3 引用队列

在对象被回收之前,可以放到引用队列里面,那么GC之后输出该对象,为null,但是输出引用队列的话,值为该对象,但是再输出一次的话就为null了。
可以在对象被回收之前在做一些事情。(“类似于“死缓” ”)

5.3 .1 引用队列代码实例

package InterviewTest;

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

public class ReferenceQueueDemo {

	public static void main(String[] args) throws Exception {
		Object o1 = new Object();
		ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
		WeakReference<Object> weakReference = new WeakReference<Object>(o1,referenceQueue);
		
		System.out.println(o1);
		System.out.println(weakReference.get());
		System.out.println(referenceQueue.poll());
		System.out.println("**************");
		o1=null;
		System.gc();
		
		Thread.sleep(500);
		
		System.out.println(o1);
		System.out.println(weakReference.get());
		System.out.println(referenceQueue.poll());
		System.out.println("-----");
		System.out.println(referenceQueue.poll());
	}
}

6 总结

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值