Effective Java之消除过期的引用(六)
容易出現內存泄漏問題的情景:
1.自己管理內存的類。
書中舉出了一個內存泄漏的stack例子
class Stack{public Object[] elements;//原文為private,但這里改為public為了測試下面代碼public int size=0;public Stack(int initialCapacity){this.elements=new Object[initialCapacity];}public void push(Object e){ensureCapacity();elements[size++]=e;}public Object pop() throws Exception{if(size==0)throw new Exception();return elements[--size];}private void ensureCapacity(){if(elements.length==size){Object[] oldElements=elements;elements=new Object[2*elements.length+1];System.arraycopy(oldElements,0,elements,0,size);}}}看了代碼,我們很容易發現,這個stack很容易發生內存泄漏,原因很簡單,pop出來的那個元素并沒有設成null,仍然有引用指向它,所以并沒有被回收。
有了這個例子,我們就可以知道,容易發生內存泄漏的情況是:
類自己管理內存,類中的元素需要釋放時,沒有做釋放的工作。所以只要是類自己管理內存都要小心翼翼。
2.緩存
為了加快訪問速度,常用的方法是進行緩存,但是開發者很多時候會忘了緩存的存在,不及時釋放,時間一長就會出現內存泄漏,所有需要進行及時清理,這里可以額外的線程,如Timer或者ScheduledThreadPoolExcutor解決。
3.監聽器和其他回調
例子:
public class MainActivity extends AppCompatActivity implements OnNetworkChangedListener {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);NetworkManager.getInstance().registerListener(this);}@Overridepublic void onNetworkUp() {}@Overridepublic void onNetworkDown() {} }AppCompatActivity實現一個接口OnNetworkChangedListener,用來監聽網絡的變化。然后,把這個監聽器注冊到NetworkManager實例中。
NetworkManager實例持有監聽器(MainActivity是實現者,指向MainActivity對象的引用)。
當NetworkManger實例的生命周期比MainActivity長,當MainActivity銷毀時(比如屏幕發生旋轉),NetworkManager實例還沒有銷毀,它持有指向MainActivity對象的引用。系統回調MainActivity的onDestroy方法,這時,GC是要回收MainActivity對象的,但是,MainActivity對象依然可達(NetworkManager實例持有指向MainActivity對象的引用),所以沒有回收,MainActivity對象泄露。
簡單來說,對象銷毀時,如果它依然被監聽,那么GC無法回收。
總結
以上是生活随笔為你收集整理的Effective Java之消除过期的引用(六)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Effective Java之避免创建不
- 下一篇: Effective Java之覆盖equ