內存溢出與內存泄露
一、定義
- 內存溢出: 即為out of memory, 當你要求分配的內存超過了系統給你的內存時, 系統就會拋出out of memory的異常(每個Android能用的內存是有限的)
比如: 當前應用只剩下4M的空間可用, 但你卻加載得到一個需要占用5M空間的圖片Bitmap對象, 就會拋出溢出的異常
- 內存泄露: 即為memory leak, 一個對象被創建后, 你不再使用它了, 但因為某種原因它又沒有成為垃圾對象, 這塊內存不能再被分配置使用.
比如: 查詢數據庫得到的cursor對象在使用完后沒有關閉, Activity中使用Handler發延遲消息, 但退出前不移除未處理的消息
- 內存泄露不多時沒有太大影響, 但積累得多了就會導致應用運動緩慢, 到最后就會內存溢出.
二、內存泄漏的分類
- 常發性內存泄漏: 發生內存泄漏的代碼會被多次執行到,每次被執行的時候都會導致一塊內存泄漏
- 偶發性內存泄漏: 發生內存泄漏的代碼只有在某些特定環境或操作過程下才會發生。常發性和偶發性是相對的。對于特定的環境,偶發性的也許就變成了常發性的
- 一次性內存泄漏: 發生內存泄漏的代碼只會被執行一次,或者由于算法上的缺陷,導致總會有一塊僅且一塊內存發生泄漏
???說明: 危害性大小順序為: ?1)>2)>3)
三、造成內存泄露的幾種場景
- 長生命周期的對象持有短生命周期對象的引用: ?Activity中使用Handler
- 資源數據連接相關對象不關閉: cusor, stream, connection
- HashSet中的對象或HashMap中的Key對象, 基內部與hash值相關的屬性被修改
- 一些對象產生后不會自動釋放或需要完全執行完了才釋放. 比如: Bitmap, Thread, AsyncTask
四、避免內存泄露
- 盡早釋放無用對象的引用
- 使用字符串處理,避免使用String,應大量使用StringBuffer,每一個String對象都得獨立占用內存一塊區域
- 盡量少用靜態變量,因為靜態變量存放在永久代(方法區),永久代基本不參與垃圾回收
- 避免在循環中創建對象
五、造成內存溢出的的場景
- 申請了太多的對象. 比如: 使用ListView時, 不復用convertView, 當數據項多時就會出現內存溢出
- 創建的對象內存太大. 比如: 不經過壓縮直接加載大圖片文件
- 內存泄露積累一定的時間后就可能出現
六、避免內存溢出
- 通過復用對象的方式, 減少產生的對象
- 大對象需要先壓縮后創建
- 避免或減少內存泄露的情況