前端时间看见java四种引用的介绍,
觉得软引用看起来可以用作内存优化.
然后看博客说,LRU内部是维护了一个有强引用的LinkedHashMap,他会根据算法将最靠前的资源从集合中移除.并没有使用到软引用.
所以请问一下,java的软引用或者弱引用在android中有应用场景吗?
LRU这样的做法,除了让缓存更大可能被复用到,还有其他优势吗?
20:56 增加
看到一篇博客说android2.3(api9)开始,内存回收器即使在内存充足的情况下,软引用和弱引用指向的对象依然有可能被回收.
那么这样的话利用弱引用来创建的Handler用于防止Handler内存泄露的方案是不是很不可靠?
//代码引用自博客
public class TestReferenceActivity extends BaseActivity {
static class MyHandler extends Handler {
private WeakReference<TestReferenceActivity> reference;
public MyHandler(Activity activity) {
//使用弱引用包裹当前的activity
reference = new WeakReference(activity);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_reference);
//解决Handler可能造成的内存泄露
//通过弱引用实现,如果当前activity需要被回收了,而且Handle持有的
//activity是被弱引用包装的,则垃圾回收器可以释放掉此activity。
MyHandler myHandler = new MyHandler(this);
}
}
소프트 참조는 실제로 2.3 시스템 이후 원래 기능이 제한되었지만 여전히 사용할 수 있지만 기본 JVM에서처럼 Android의 GC 중에 쉽게 재활용되지 않습니다. 특정 용도로 사용하려면 이 기사를 추천합니다
소프트 참조와 약한 참조는 사용할 수 없지만 동작을 예측할 수 없습니다.
약하게 참조된 리소스가 언제 재활용될지 정확히 알 수 없습니다. 일반적인 이미지 캐싱 상황에서는 LRU 알고리즘이 약한 참조보다 효율적이며 리소스의 다중 생성/재활용을 효과적으로 방지할 수 있습니다.
약한 참조는 메모리 누수가 발생하기 쉬운 특정 상황에 더 적합합니다. 예를 들어 AsyncTask에서는 약한 참조를 사용하여 메모리 누수를 방지할 수 있습니다.
소프트 참조는 실제로 이미지의 비동기 로딩과 같은 실제 Android 개발에 매우 유용합니다. 가장 일반적인 것은 imageloder가 캐시 최적화를 처리할 때도 소프트 참조를 사용한다는 것입니다. 성능 최적화에는 그다지 도움이 되지 않습니다. 주로 oom에 좋은 처리가 필요한 경우에는 약한 참조를 사용하는 것이 좋습니다
답변을 마친 후에도 질문 아래에 여전히 질문이 있는 것을 확인했습니다. 실제로 핸들러 OOM을 방지하기 위해 소프트 참조를 사용하는 이유는 Android 메인 스레드가 생성될 때 발생하는 특수한 메커니즘 때문입니다. Looper 객체는 MessageQueue를 구현합니다. 핸들러 객체를 생성할 때 핸들러를 사용하여 MessageQueue에 메시지를 넣을 때마다 메시지는 핸들러 객체에 대한 참조를 보유합니다. 따라서 활동이 종료되면 메시지가 제거되기 전에 이 메시지가 항상 존재하며 메시지는 핸들러에 대한 참조를 보유합니다. 핸들러는 활동에 생성되며 따라서 이 활동에 대한 참조를 보유하게 됩니다. gc로 재활용할 수 없으며 OOM이 발생합니다. Java의 모든 비정적 개체는 현재 개체에 대한 강력한 참조를 보유하는 반면 정적 개체는 현재 클래스에 대한 약한 참조만 보유합니다. 이는 활동이 종료되면 메시지를 처리할 수 없어 메시지가 영구적으로 발생하는 문제를 해결합니다. 핸들러 참조를 보유하면 핸들러는 활동에 대한 참조를 영구적으로 보유합니다.