四种类型
强引用(Strong Reference)
经常使用,内存不足,抛出OOM异常使程序异常终止。不会回收强引用对象来解决内存不足问题
软引用(Soft Reference)
当无强引用指向时,会在内存中停留一段时间。垃圾回收器根据JVM内存使用情况及SoftReference.get()调用情况决定是否对其回收
弱引用(Weak Reference)
只要垃圾回收器对其回收,无论内存使用情况如何,均回收(WeakReference.get()返回null)
虚引用 (Phantom Reference)
PhantomReference.get()永远返回null,因此无法通过get()获取目标对象的强引用从而使用对象
引用对列 (Reference Queue)
当检测到对象可达性变化后,垃圾回收器将已注册的引用对象添加到此队列中。一旦弱引用对象返回null,则该弱引用所指向的对象被标记为垃圾,弱引用对象变为无用。此时需进行清理工作,如WeakHashMap移除没用的条目来避免保存无限制增长的无意义的弱引用。
引用类型特性总结
引用类型 | 取得目标对象方式 | 垃圾回收条件 | 是否可能内存泄漏 |
强引用 | 直接调用 | 不回收 | 可能 |
软引用 | 通过 get() 方法 | 视内存情况回收 | 不可能 |
弱引用 | 通过 get() 方法 | 永远回收 | 不可能 |
虚引用 | 无法取得 | 不回收 | 可能 |
实例
SoftReference softReference = new SoftReference(buff); //软引用
WeakReference weakReference = new WeakReference(buff); //弱引用
ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>(); //引用队列
PhantomReference<Object> referent = new PhantomReference<>(new Object(), refQueue); //虚引用
System.out.println(referent.get()); //null
System.gc();
System.runFinalization();
软引用获取Bitmap对象
//定义一个HashMap,保存软引用对象
Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>();
//添加软引用对象到缓存(imageCache)中
Bitmap bitmap = BitmapFactory.decodeFile(path);
SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>(bitmap);
imageCache.put(path, softBitmap);
//从软引用中获取Bitmap对象
SoftReference<Bitmap> softBitmap = imageCache.get(path);
if (softBitmap != null) {
Bitmap bitmap = softBitmap.get(); //通过get()获取软引用指向的对象
}
问题
为什么Android官方废弃SoftRefrerence软引用和WeakReference弱引用,而拥抱LruCache?
使用软引用时,在内存出时,无法决策是清除已存在的软引用还是申请增大内存。如果需要清除已存在的软引用,软引用间无优先级,无法决定先清除谁
LruCache可根据变量的使用频次来决定先清除谁
GC判断为垃圾的对象一定会回收吗
不会,需要两次标记。
第一次标记并筛选,筛选出对象是否要执行finalize,如果对象没有重写finalize方法,或者finalize已被虚拟机调用过,就是没有必要执行,直接回收
如果不是上述情况,则有必要执行finalize,则GC将对象放在F-Queue对象,由Finializer线程执行finalize
强引用置为null,会不会被回收?
不会立即被回收,置为null后,只是将此对象的"根去除掉"。概念参照GC回收算法。
静态 类型变量必须及时赋值为null,否则其生命周期与应用程序一致