1 概述
引用类型 | 被回收时间 | 用途 | 生存时间 |
---|---|---|---|
强引用 | 从来不会 | 对象的一般状态 | JVM停止运行时 |
软引用 | 内存不足时 | 对象缓存 | 内存不足时 |
弱引用 | JVM垃圾回收时 | 对象缓存 | GC运行后 |
虚引用 | 未知 | 未知 | 未知 |
2 强引用(StrongReference)
开发中,定义的引用一般都是强引用,这是最普遍的使用。如果一个对象具有强引用,就是必不可少
的对象,不会被垃圾回收器回收。
当内存空间不足时,JVM宁愿抛出OOM异常,使程序终止,也不回收这种引用
// object和str 都是强引用
Object object = new Object();
String str = "123";
如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为 null,
这样,JVM 会在合适的时间回收该对象。
ArrayList类
的 clear()方法,就是通过将引用赋值为 null,来实现清理工作的。
public void clear(){
modCount++;
// Let gc do its work
for(int i=0; i<size;i++)
elementData[i] = null;
size = 0;
}
在ArrayList类中定义了一个私有的变量elementData数组,在调用方法清空数组时可以看到为每个数组内容赋值为null。不同于elementData=null,强引用仍然存在,避免在后续调用 add()等方法添加元素时进行重新的内存分配。使用如clear()方法中释放内存的方法对数组中存放的引用类型特别适用,这样就可以及时释放内存。
3 软引用(SoftReference)
软引用,弱引用都可以和一个引用队列(ReferenceQueue)
联合使用,虚引用必须和引用队列联合使用
。在实际开发中,软引用最常用,弱引用和虚引用很少使用
ReferenceQueue<String> queue = new ReferenceQueue<String>();
PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);
软引用是用来描述一些有用但不是必需
的对象,在 Java中用 java.lang.ref.SoftReference
类来表示。
对于软引用关联着的对象,只有在内存不足的时候,JVM才会回收该对象
。因此,这一点可以很好地用来解决OOM的问题,并且这个特性,很适合用来实现缓存:比如网页缓存,图片缓存等。
如何利用软引用和弱引用解决OOM问题
假如有一个应用需要读取大量的本地图片。如果每次读取图片都从硬盘读取,会严重影响性能;但是如果全部加载到内存中,有可能造成内存溢出。此时,使用软引用可以解决这个问题。
设计思路
用一个 HashMap 来保存图片的路径 和 相应的图片对象 关联的软引用 之间的映射关系。
当内存不足时,JVM 会自动回收这些缓存图片对象,所占用的空间,从而有效的避免了 OOM问题
在 Android开发中,对于大量图片下载会经常用到
private Map<String, SoftReference<Bitmap>> imageCache = new
HashMap<String,SoftReference<Bitmap>>();
public void addBitmapToCache(String path){
// 强引用的 Bitmap对象
Bitmap bitmap = BitmapFactory.decodeFile(path);
// 软引用的 Bitmap对象
SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>(bitmap);
//添加该对象到 Map中 使其缓存
imageCache.put(path,softBitmap);
}
public Bitmap getBitmapByPath(String path){
// 从缓存中 取软引用的 Bitmap对象
SoftReference<Bitmap> softBitmap = imageCache.get(path);
// 判断 是否存在软引用
if(softBitmap == null){
return null;
}
// 取出 Bitmap对象,如果由于内存不足 Bitmap被回收,将取得空
Bitmap bitmap = softBitmap.get();
return bitmap;
}
4 弱引用(WeakReference)
弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中,用 java.lang.ref.WeakReference
类来表示。
弱引用与软引用的区别:被软引用关联的对象只有在内存不足时才会被回收,而被弱引用关联的对象在JVM进行垃圾回收时总会被回收
。
只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程, 因此不一定会很快发现那些只具有弱引用的对象。
使用场景
如果一个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么应该用 Weak Reference 来记住此对象。或者想引用一个对象,但是这个对象有自己的生命周期,你不想介入这个对象的生命周期,这时候就应该用弱引用,这个引用不会在对象的垃圾回收判断中产生任何附加的影响。
5 虚引用(PhantomReference)
- 虚引用和前面的软引用、弱引用不同,它
并不影响对象的生命周期
在任何时候都可能被垃圾回收器回收
(对象与虚引用关联和不关联效果一样)- 虚引用主要用来跟踪对象被垃圾回收的活动
虚引用必须和引用队列关联使用
- 在 Java 中用
java.lang.ref.PhantomReference类
表示