Java四种引用类型java
1.引用的基本概念面试
强引用:当咱们使用new建立对象时,被建立的对象就是强引用,如Object object = new Object(),其中的object就是一个强引用了。若是一个对象具备强引用,JVM就不会去GC它,JVM宁肯会报OOM来终止程序,也不回收该对象。编程
软引用: 若是一个对象只具有软引用,若是内存空间足够,那么JVM就不会GC它,若是内存空间不足了,就会GC该对象。缓存
弱引用: 若是一个对象只具备弱引用,只要JVM的GC线程检测到了,就会当即回收。弱引用的生命周期要比软引用短不少。不过,若是垃圾回收器是一个优先级很低的线程,也不必定会很快就会释放掉软引用的内存。spa
虚引用:若是一个对象只具备虚引用,那么它就和没有任何引用同样,随时会被JVM看成垃圾进行GC。线程
上面的四种引用对应的是new关键字以及java.lang.ref包中的SoftReference,WeakReference, PhantomReference。咱们注意到在java.lang.ref包中,还存在一个类叫作ReferenceQueue。3d
在Java中提供了四个级别的引用:强引用,软引用,弱引用和虚引用。在这四个引用类型中,只有强引用FinalReference类是包内可见,其余三种引用类型均为public,能够在应用程序中直接使用。引用类型的类结构如图所示。指针
平时咱们编程的时候例如:Object object=new Object();那object就是一个强引用了。若是一个对象具备强引用,那就相似于必不可少的生活用品,垃圾回收器毫不会回收它。当内存空 间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具备强引用的对象来解决内存不足问题。对象
Java中的引用,相似C语言中最难的指针。(我是C语言入门编程,指针的概念仍是很深刻我心。)经过引用,能够对堆中的对象进行操做。如:blog
StringBuffer stringBuffer = new StringBuffer("Helloword");
变量str指向StringBuffer实例所在的堆空间,经过str能够操做该对象。
强引用的特色:
若是一个对象只具备软引用,那就相似于可有可物的生活用品。若是内存空间足够,垃圾回收器就不会回收它,若是内存 空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就能够被程序使用。软引用可用来实现内存敏感的高速缓存。 软引用能够和一个引用队列(ReferenceQueue)联合使用,若是软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联 的引用队列中。
软引用是除了强引用外,最强的引用类型。能够经过java.lang.ref.SoftReference使用软引用。一个持有软引用的对象,不会被JVM很快回收,JVM会根据当前堆的使用状况来判断什么时候回收。当堆使用率临近阈值时,才会去回收软引用的对象。所以,软引用能够用于实现对内存敏感的高速缓存。
SoftReference的特色是它的一个实例保存对一个Java对象的软引用, 该软引用的存在不妨碍垃圾收集线程对该Java对象的回收。也就是说,一旦SoftReference保存了对一个Java对象的软引用后,在垃圾线程对 这个Java对象回收前,SoftReference类所提供的get()方法返回Java对象的强引用。一旦垃圾线程回收该Java对象以后,get()方法将返回null。
下面举一个例子说明软引用的使用方法。
在你的IDE设置参数-Xmx2m -Xms2m规定堆内存大小为2m。
运行结果:
打开被注释掉的new byte[1024*100]语句,这条语句请求一块大的堆空间,使堆内存使用紧张。并显式的再调用一次GC,结果以下:
说明在系统内存紧张的状况下,软引用被回收。
若是一个对象只具备弱引用,那就相似于可有可物的生活用品。弱引用与软引用的区别在于:只具备弱引用的对象拥有更 短暂的生命周期。在垃圾回收器线程扫描它 所管辖的内存区域的过程当中,一旦发现了只具备弱引用的对象,无论当前内存空间足够与否,都会回收它的内存。不过,因为垃圾回收器是一个优先级很低的线程, 所以不必定会很快发现那些只具备弱引用的对象。 弱引用能够和一个引用队列(ReferenceQueue)联合使用,若是弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联 的引用队列中。
弱引用是一种比软引用较弱的引用类型。在系统GC时,只要发现弱引用,无论系统堆空间是否足够,都会将对象进行回收。在java中,能够用java.lang.ref.WeakReference实例来保存对一个Java对象的弱引用。
运行结果:
软引用,弱引用都很是适合来保存那些无关紧要的缓存数据,若是这么作,当系统内存不足时,这些缓存数据会被回收,不会致使内存溢出。而当内存资源充足时,这些缓存数据又能够存在至关长的时间,从而起到加速系统的做用。
5、虚引用(PhantomReference):
“虚引用”顾名思义,就是形同虚设,与其余几种引用都不一样,虚引用并不会决定对象的生命周期。若是一个对象 仅持有虚引用,那么它就和没有任何引用同样,在任什么时候候均可能被垃圾回收。 虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,若是发现它还有虚引用,就会在回收对象的内存以前,把这个虚引用加入到与之 关联的引用队列中。程序能够经过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序若是发现某个虚引用已经被加入到引用队 列,那么就能够在所引用的对象的内存被回收以前采起必要的行动。
在java.lang.ref包中提供了三个类:SoftReference类、WeakReference类和PhantomReference类,它们分别表明软引用、弱引用和虚引用。ReferenceQueue类表示引用队列,它能够和这三种引用类联合使用,以便跟踪Java虚拟机回收所引用的对象的活动。
虚引用是全部类型中最弱的一个。一个持有虚引用的对象,和没有引用几乎是同样的,随时可能被垃圾回收器回收。当试图经过虚引用的get()方法取得强引用时,老是会失败。而且,虚引用必须和引用队列一块儿使用,它的做用在于跟踪垃圾回收过程。
当垃圾回收器准备回收一个对象时,若是发现它还有虚引用,就会在垃圾回收后,销毁这个对象,将这个虚引用加入引用队列。程序能够经过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。若是程序发现某个虚引用已经被加入到引用队列,那么就能够在所引用的对象的内存被回收以前采起必要的行动。
运行结果:
对虚引用的get()操做,老是返回null,由于sf.get()方法的实现以下:
6、弱引用典例
WeakHashMap类在java.util包内,它实现了Map接口,是HashMap的一种实现,它使用弱引用做为内部数据的存储方案。WeakHashMap是弱引用的一种典型应用,它能够做为简单的缓存表解决方案。
如下两段代码分别使用WeakHashMap和HashMap保存大量的数据:
使用-Xmx2M限定堆内存,使用WeakHashMap的代码正常运行结束,而使用HashMap的代码段抛出异常
因而可知,WeakHashMap会在系统内存紧张时使用弱引用,自动释放掉持有弱引用的内存数据。
但若是WeakHashMap的key都在系统内持有强引用,那么WeakHashMap就退化为普通的HashMap,由于全部的表项都没法被自动清理。