四种引用的对比
类型 | 回收机制 | 用途 | 生存时间 |
---|---|---|---|
强引用 | 从不回收 | 对象的状态 | JVM停止运行时 |
软引用 | 内存不足时回收 | 缓存 | 内存不足时 |
弱引用 | 对象没有被引用时回收 | 缓存 | 对象回收时 |
虚引用 | 对象被回收时 | 管理精准控制内存的稳定性 | 未知 |
强引用
强引用时平时我们最经常用的一种引用,例如直接new一个对象。
String str=new String();
强引用具有如下的特点:
- 即使发生OOM也不不会发生回收
- 强引用可以直接使用目标对象
- 强引用在引用对象null时会导致内存泄漏
软引用
A a=new A();
SoftReference reference=new SortReference(a);
一个对象只有软引用时,内存足够时,则不会被回收,当内存不够时被回收,只有内存不足的时候才会回收软引用。需要注意的时在使用的时候要判断软引用对象是否为空。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
ReferenceQueue queue = new ReferenceQueue();
SoftReference softReference=new SoftReference(a, queue);
Android中的例子
- 缓存图片的时候可以使用软引用缓存,当我们获取图片的时候可以通过HashMap进行缓存,下次获取的时候直接通过key来获取,这个时候我们可以使用软引用,这样可以防止内存不足时发生OOM。
private Map<String,SoftReference> softReferenceMap=new HashMap<>();
/**
*
* @param path
*/
public void addBitmap(String path){
// 强引用的Bitmap对象
Bitmap bitmap = BitmapFactory.decodeFile(path);
// 软引用的Bitmap对象
SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>(bitmap);
// 添加softBitmap到Map中使其缓存
softReferenceMap.put(path, softBitmap);
}
/**
*
* @param path
* @return
*/
public Bitmap getBitmap(String path) {
// 从缓存中取软引用的Bitmap对象
SoftReference<Bitmap> softBitmap = softReferenceMap.get(path);
// 判断是否存在软引用
if (softBitmap == null) {
return null;
}
// 取出Bitmap对象,如果由于内存不足Bitmap被回收,将取得空
Bitmap bitmap = softBitmap.get();
return bitmap;
}
- 在加载过大的图片的时候可以使用软引用,但是要注意的是在使用的时候要判断一个是否为空。
public class SoftReferenceActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ImageView imageView=new ImageView(this);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inPreferredConfig= Bitmap.Config.ARGB_4444;
options.inPurgeable= true;
options.inInputShareable= true;
options.outWidth= 720;
options.outHeight= 1280;
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher_round,options);
Drawable drawable=new BitmapDrawable(getResources(),bitmap);
SoftReference<Drawable> drawableSoftReference =
new SoftReference<Drawable>(drawable);
if(drawableSoftReference != null) {
//内存不足将不显示
imageView.setBackground(drawableSoftReference.get());
}
}
}
弱引用
A a=new A();
WeakReference<A> reference=new WeakReference<>(a);
特点:
如果一个对象只具有弱引用的时候,当垃圾回收线程扫描到之后,内存无论是否足够,都进行回收。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
Android中的例子
当我们使用Handler执行异步耗时任务的时候,如果我们的Activty关闭时,此时应该要回收Activity对象的,但是因为Handler持有Activity的引用,就会导致OOM
解决办法:
- 在Activity关闭的地方将线程停止以及把Handler的消息队列的所有消息对象移除
- 将Handler改为静态内部类,但是因为静态内部类不持有外部类的引用,所以我们可以通过弱引用的方式。
public class WeakReferenceActivity extends AppCompatActivity {
private WeakReference<WeakReferenceActivity> reference;
private MyHandler myHandler = new MyHandler(this);
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myHandler.sendEmptyMessage(1);
}
public static class MyHandler extends Handler {
private WeakReference<WeakReferenceActivity> reference;
public MyHandler(WeakReferenceActivity activity) {
reference = new WeakReference<WeakReferenceActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
WeakReferenceActivity weakReferenceActivity = (WeakReferenceActivity) reference.get();
if (weakReferenceActivity != null) {
System.out.print("WeakReferenceActivity");
}
break;
default:
break;
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
myHandler.removeCallbacksAndMessages(null);
}
}
虚引用
作用就是跟踪对象合适被回收,但是必须要和引用队列 (ReferenceQueue)联合使用。当垃圾回收机制准备回收一个对象的时候,如果发现这个对象还存在一个虚引用,就会在这个对象被回收之前将这个虚引用加入到引用队列中,如果在引用队列中发现虚引用,那么就说明与之关联的对象将要被回收了。
参考链接:
网友评论