前言:
Java种除了基本数据类型,其它数据类型都是引用的数据类型。而应用数据类型根据生命周期的长短又分为:强引用、弱引用、软引用和需引用(幻象引用),我们平时基本上只用到强引用类型,而其他的引用类型我们也就在面试中,或者平日阅读类库或其他框架源码的时候才能见到。
1、强引用:
描述:
强引?是使用最普遍的引用。如果?个对象具有强引用,那垃圾回收器绝不会回收它。 当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引?的对象来解决内存不足的问题。
代码实例:
Object obj = new Object();
2、软引用(SoftReference):
描述:
如果内存空间不足了,就会回收这些对象的内存。 软引用可以和?个引用队列(ReferenceQueue)联合使用 如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加?到与之关联的引用队列中。
代码实例:
// 普通创建
Object obj1 = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj1);
obj = null; // 移除强引用
System.out.println("软引用1: " + sf.get());//获取对象
// 队列创建
Object obj2 = new Object();
ReferenceQueue queue2 = new ReferenceQueue();
SoftReference<Object> sf2 = new SoftReference<Object>(obj2, queue2);
obj2 = null; // 移除强引用
System.out.println("软引用2: " + sf2.get());//获取对象
System.out.println("软引用队列: " + queue2.poll());
用途:
比如考虑一个图像编辑器的程序。 该程序会把图像文件的全部内容都读取到内存中,以方便进行处理。 而用户也可以同时打开多个文件。当同时打开的文件过多的时候,就可能造成内存不足。 如果使用软引用来指向图像文件内容的话,垃圾回收器就可以在必要的时候回收掉这些内存。
3、弱引用(WeakReference):
描述:
- 弱引?与软引用的区别在于:只具有弱引用的对象拥有更短暂的?命周期。
- 在垃圾回收器线程扫描它所管辖的内存区域的过程中,?旦发现了只具有弱引用的对象,不管当前内存空间足够与否, 都会回收它的内存。
- 弱引?可以和?个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加?到与之关联的引用队列中。
代码实例:
// 不使用队列
Object obj3 = new Object();
WeakReference<Object> wf1 = new WeakReference<>(obj3);
obj3 = null; // 移除强引用
System.out.println("弱引用1: " + wf1.get());//获取对象
// 配合队列使用
Object obj4 = new Object();
ReferenceQueue queue3 = new ReferenceQueue();
WeakReference<Object> wf2 = new WeakReference<Object>(obj4, queue3);
obj2 = null; // 移除强引用
System.out.println("弱引用2: " + wf2.get());//获取对象
System.out.println("弱引用队列: " + queue3.poll());
用途:
弱引用的作用在于解决强引用所带来的对象之间在存活时间上的耦合关系。弱引用最常见的用处是在集合类中,尤其在哈希表中。哈希表的接口允许使用任何Java对象作为键来使用。当一个键值对被放入到哈希表中之后,哈希表对象本身就有了对这些键和值对象的引用。如果这种引用是强引用的话,那么只要哈希表对象本身还存活,其中所包含的键和值对象是不会被回收的。如果某个存活时间很长的哈希表中包含的键值对很多,最终就有可能消耗掉JVM中全部的内存。
对于这种情况的解决办法就是使用弱引用来引用这些对象,这样哈希表中的键和值对象都能被垃圾回收。Java中提供了WeakHashMap来满足这一常见需求
ThreadLocal中的key就用到了弱引用。
4、虚引用(PhantomReference):
描述:
- 虚引用在任何时候都可能被垃圾回收器回收
- 虚引用与软引用和弱引用的?个区别在于:
- 虚引用必须和引用队列 (ReferenceQueue)联合使用。
- 当垃圾回收器准备回收?个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加?到与之关联的引用队列中。
- 创建后无法通过虚引用获取到对象
代码实例:
Object obj5 = new Object();
ReferenceQueue queue = new ReferenceQueue();
PhantomReference<Object> pf = new PhantomReference<Object>(obj5, queue);
obj5 = null; // 移除强引用
System.gc();
System.out.println("GC后虚引用中对象:" + pf.get());
System.out.println("GC后队列中对象: " + queue.poll());
用途:
主要用来跟踪对象被垃圾回收器回收的活动,被回收时会收到?个系统通知。
统计:
引用类型 | 引用时对象创建方式 | gc 影响 | 一般用途 |
---|
强引用 | Object obj = new Object(); | 对象被引用时,永远不会回收 | 99%对象创建形式 | 软引用 | SoftReference softObj = new SoftReference(obj) | JVM认为内存空间不足时,回收软引用指向的对象 | 图片缓存框架中缓存图片 | 弱引用 | WeakReference weakObj = new WeakReference(obj); | GC时不管内存是否充足都会回收这个对象 | ThreadLoacl key使用了弱引用 | 虚引用 | PhantomReference<byte[]> ref = new PhantomReference<byte[]>(data, queue) | 任何时候都可能被GC回收和未被引用一样 | 可以用来跟踪对象被垃圾回收的活动 |
Ending !!!!
|