Java中的强引用,软引用,弱引用,虚引用有什么用?

每一种语言都有着自己操作内存元素的方式,C语言通过指针,而java就是通过引用。作为一门面向对象的语言,在java中世事万物皆对象。但是我们操作的标识符实际上是对象的一个引用(reference)。今天我们来分析一下java中的四种引用。

一、引用的历史

在Java中,我们的垃圾回收机制回收垃圾对象的时候就会依据对象的引用。比如说通过不同的垃圾回收算法,这里有两种:引用计数法和可达性分析法

1、引用计数法:为每个对象添加一个引用计数器,每当有一个引用指向它时,计数器就加1,当引用失效时,计数器就减1,当计数器为0时,则认为该对象可以被回收。

2、可达性分析算法:从一个被称为 GC Roots 的对象开始向下搜索,如果一个对象到GC Roots没有任何引用链相连时,则说明此对象不可用。



目前的垃圾回收基本上采用第二种方式,第一种方式基本上已经被舍弃了。

在jdk1.2之前,java对引用的概念只有“已被引用”和"未被引用"两种状态。后来所以在 JDK.1.2 之后,Java 对引用的概念进行了扩充,将引用分为了:强引用、软引用、弱引用、虚引用4 种,也就是我们今天所讲的主题。这 4 种引用的强度依次减弱。

二、四种引用

1、强引用

如果一个对象具有强引用,它就不会被垃圾回收器回收。即使当前内存空间不足,JVM也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。比如String str = "hello"这时候str就是一个强引用。当然我们也可以使用str=null取消一个强引用。下面我们使用代码来测试一下强引用:

前提是我们先要设置一些jvm参数, -Xms2M -Xmx3M表示初始内存是2M,最大内存是3M。设置的步骤如下:

步骤:
1、选中已经写好的项目
2、Run->Debug configurations->Java Application 双击
3、Arguments->VM arguments
4、在VM arguments 里面就可以对虚拟机的内存参数进行设置
5、设置完成后,Apply->Debug

 
public class Test{
	public static void main(String[] args){
		testStrongReference();
	}
	private static void testStrongReference() {
		//1M的时候是正常的,但是我们调到3M这时候就会出现OutOfMemoryError
		byte[] buff = new byte[1024 * 1024 * 3];
	}
}

2、软引用

如果一个对象具有软引用,它就不会被垃圾回收器回收。只有在内存空间不足时,软引用才会被垃圾回收器回收。这种引用常常被用来实现缓存技术。因为缓存区里面的东西,之后在内存不足的时候才会被清空。下面我们再进行测试一下:前提是设置虚拟机参数 -Xms2M -Xmx3M。

 
private static void testSoftReference() {
	//创建10个大小为1M的字节,赋值给软引用
	for (int i = 0; i < 10; i++) {
		byte[] buff = new byte[1024 * 1024];
		SoftReference<byte[]> sr = new SoftReference<>(buff);
		list.add(sr);
	}
	//主动通知JVM,建议回收
	System.gc();
	//循环遍历出来
	for(int i=0; i < list.size(); i++){
		Object obj = ((SoftReference) list.get(i)).get();
		System.out.println(obj.toString());
	}
}

我们可以测试一下,会发现只有最后一个软引用对象打印了出来,其他的全部为null。这是为什么呢?这是因为我们设置的参数是最大3M,内存不足的时候,会主动回收这些对象垃圾。

3、弱引用

如果一个对象具有弱引用,在垃圾回收时候,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象。我们把上面的对象如果改成弱引用的话,你会发现所有的全部为空,这就是因为创建了10个1M的对象,超出了3M,无论内存是否足够,都会被回收。

4、虚引用

如果一个对象具有弱引用,就相当于没有引用,在任何时候都有可能被回收。虚引用是使用PhantomReference创建的引用,虚引用也称为幽灵引用或者幻影引用,是所有引用类型中最弱的一个。一个对象是否有虚引用的存在,完全不会对其生命周期构成影响,也无法通过虚引用获得一个对象实例。

使用虚引用的目的就是为了得知对象被GC的时机,所以可以利用虚引用来进行销毁前的一些操作,比如说资源释放等。这个虚引用对于对象而言完全是无感知的,有没有完全一样,但是对于虚引用的使用者而言,就像是待观察的对象的把脉线,可以通过它来观察对象是否已经被回收,从而进行相应的处理。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值