在電腦世界裡,有一個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(註一)。
 
如果以上的文字,你讀起來就像外星文的話,也沒關係,只要你能了解以下的事即可。Memory Leak的狀況,就比如有一天你讀了的某一本書,本來這本書的資訊好好存在你腦中,但是有一天你腦中本來連結到這本書的線突然間消失了,所以這個資訊仍然原原本本的存在腦中,但是你沒有辦法去忘記它或是去想起它,如果這樣的情況愈來愈多,你腦中就會一直被這些無法存取的記憶佔據,直到腦容量用完為止(這裡是假設人腦真的有個極限)。
 
而我想講的,其實就是上述這個狀況,我自己稱它叫作Human Brain’s Memory Leak(人腦的記憶體漏洩)。
 
我以前的Memory Leak情況就偶而有之。聽到某首已經聽了幾百次的歌却怎麼樣也想不起演唱者,直到幾天後,上廁所時才突然想起。和朋友描述到某個人的時候,腦中可以清楚描繪出那個人的長相、衣著與身體特徵,卻怎麼也想不起對方的名字,只好和朋友玩起猜一猜的遊戲-你記不記得我們在某個地方有看過他? 他大概有171高,每次都是穿高腰牛仔褲那個男的,通常朋友們也只能無奈的陪我回想對方的名字。我知道這些資訊都還在我腦中,要不然我不會幾天後才想到或是一聽到正確答案就有反應,但是在我需要他們時,那條指引的線卻無情的消失了,直到想到那一刻,腦中那消失的線才又再度重建起來。
 
隨著年紀增加, Memory Leak情況日趨嚴重,外加現在又多了另一個語言英文,所以每一個資訊都連繫著兩條線(雙指標),一個連到英文,一個連到中文。常常講中文時,要講某個東西時,連到那個東西的線,只有英文那條線是通的,不然就是講英文時,只有中文那條線是通的,更不用說兩條線都不通的狀況了,真的是懊惱到不行。說實在我也真的不想講中文時夾雜英文,當個會讓人討厭的假ABC/CBC;或是講英文時,只記得中文的名稱,和外國人玩猜一猜的遊戲-What ‘s that thing we ate last time? It is like this long(用手比中) and its skin is purple…,更不用說是腦中一片空白完全忘記要講的那個東西的中文與英文的狀況。第一種狀況還好只是會被人討厭,第二種狀況是會讓自己有英文不夠好的挫折(但事實上我知道或看過那個字,只是暫時想不起來呀!),第三種則是真的叫天天不應叫地地不靈。總之,三種都不是很好的經驗。
 
而且也不知道是不是腦中已經有太多Memory Leak,外加很多資訊有雙指標佔據了更多腦空間,搞的可用的腦容量大幅減少,導致現在很多新的資訊很難記的起來。很多事前一秒還記得好好的,下一秒就完全忘記,不得不懷疑是否是試圖存取資訊到腦中時,腦中回應記憶體以滿(Out of Memory ),把存取的動作給回復(rollback)了。
 
程式有Memory Leak,可用工具(如jProbe)幫忙找出臭蟲(bug),找到後還可以一併把臭蟲清除乾淨。我真心期望這世上有人可以發明能找出我腦中臭蟲的工具,讓我的腦可以正常存取資訊且老了保證不會得Alzheimer's disease(阿茲海默症)。這樣的要求算不算太多?!
 
 
 
[註一]有些人以為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裡移除即可。
 
Java的Memory Leak,大多也都是不當程式設計下的人為結果,寫程式時千萬要把這點放在心裡噢。
 
 
創作者介紹

女工程師的美加生活手札

nycEngDiary 發表在 痞客邦 PIXNET 留言(0) 人氣()