Wednesday, November 2, 2011

何謂Memory Leak(記憶體洩漏)

何謂Memory Leak?

我們常常會聽到程式開發人員嘴邊老喊著︰記憶體不足。
會發生這個問題,其中可能包含Memory Leak。


維基百科對Memory Leak(記憶體洩漏)做了以下的解釋︰

電腦科學中,內部記憶體泄漏指由於疏忽或錯誤造成程式未能釋放已經不再使用的內部記憶體的情況。
內部記憶體泄漏並非指內部記憶體在物理上的消失,而是應用程式分配某段內部記憶體後,由於設計錯誤,導致在釋放該段內部記憶體之前就失去了對該段內部記憶體的控制,從而造成了內部記憶體的浪費。
Android官方布落格提到︰

A "memory leak" in your code is when you keep a reference to an object that is no longer needed. Sometimes a single reference can prevent a large set of objects from being garbage collected.


以下文章引用自女工程師的美加生活手札的部落格,
裡面提到︰
在電腦世界裡,有一個performance的隱性敵人,它會造成記憶體的使用量隨著時間慢慢增加直到消耗殆盡,這個敵人俗稱Memory Leak (中文翻成記憶體漏洩)。

Memory Leak造成的原因是某個被配置(allocated)的記憶體無法在被參照(referenced),也無法被釋放(released);那塊被配置的 記憶體就有如記憶體孤兒般,無法被系統再使用,所以要看一個程式有否Memory Leak,很簡單的方法就是去看作業系統(For standalone application)或是Application Server(如果是Web Application)的實體記憶體使用圖,如果隨著時間增加,記憶體的使用量呈現明顯增加的趨勢,這個程式就極有可能有潛在的Memory Leak問題。
Memory Leak在C/C++語言中是很常見的人為過失,因為C/C++並沒有自動Garbage Collector (垃圾收集器)的機制,程式設計師必需在使用完資源後,人為釋放資源。雖然在Java、C#有自動Garbage Collector的機制,Memory Leak的機會大幅下降,但仍然不能完全倖免,只要程式設計師不小心仍然會造成Memory Leak。

有些人以為Java有Garbage Collector(GC)就不會有Memory Leak,其實是錯的。如果一個物件仍然有被參照,Garbage Collector是不會回收該物件的。

比如以下狀況:
假設你有一個Java程式,裡面你運用了一個宣告為static 的Array A來儲存已經開啟的視窗-JFrame instance。如果使用者開啟了一個視窗W1,W1會被存入Array A中,而當W1關閉後,你沒有把W1從Array A裡移除,這時,雖然W1已被指到null,Garbage Collector卻不會回收W1。
原因很簡單,因為Array A仍保有W1的參照,GC假設W1之後有被使用的機會,所以沒有回收W1。如果這個程式持續開關大量視窗,它所用的記憶體也會呈現增加的趨勢,而造成了典 型的Memory Leak狀況。
解決的方式很簡單,只要在W1被關閉時同時把W1從Array A裡移除即可。

相關文章︰
1.Romain Guy在Android官方討論裡提到的Memory Leak
2.Memory Leak經驗分享-Drawable篇
3.使用MAT(記憶體分析)工具查看Memory Leak
4.Android官方布落格2011/03/24
5.Android官方文件

No comments: