淺談內存溢出和內存泄漏及其如何避免內存溢出和泄漏

在程序編寫過程中,內存溢出和內存泄漏是我們經常關心的問題,如何避免內存泄漏和溢出是我們每個程序員應該必備的技能,這邊文章介紹內存溢出和泄漏已經如何避免內存溢出和內存泄漏這兩種情況的發生。

一、什麼是內存溢出
內存溢出(out of memory)通俗理解就是內存不夠,通常在運行大型軟件或遊戲時,軟件或遊戲所需要的內存遠遠超出了你主機內安裝的內存所承受大小,就叫內存溢出。
或是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory。
二、什麼是內存泄漏
內存泄漏是指程序中間動態分配了內存,但在程序結束時沒有釋放這部分內存,從而造成那部分內存不可用的情況,內存泄露和硬件沒有關係,它是由軟件設計缺陷引起的。
內存泄露一般分爲以下幾種情況:

  1. 常發性內存泄漏。發生內存泄漏的代碼會被多次執行到,每次被執行的時候都會導致一塊內存泄漏。
  2. 偶發性內存泄漏。發生內存泄漏的代碼只有在某些特定環境或操作過程下才會發生。常發性和偶發性是相對的。對於特定的環境,偶發性的也許就變成了常發性的。所以測試環境和測試方法對檢測內存泄漏至關重要。
  3. 一次性內存泄漏。發生內存泄漏的代碼只會被執行一次,或者由於算法上的缺陷,導致總會有一塊僅且一塊內存發生泄漏。比如,在類的構造函數中分配內存,在析構函數中卻沒有釋放該內存,所以內存泄漏只會發生一次。
  4. 隱式內存泄漏。程序在運行過程中不停的分配內存,但是直到結束的時候才釋放內存。嚴格的說這裏並沒有發生內存泄漏,因爲最終程序釋放了所有申請的內存。但是對於一個服務器程序,需要運行幾天,幾周甚至幾個月,不及時釋放內存也可能導致最終耗盡系統的所有內存。所以,我們稱這類內存泄漏爲隱式內存泄漏。

三、內存溢出和內存泄漏的異同點
同:都會導致應用程序運行出現問題,性能下降或掛起。
異:
1) 內存泄露是導致內存溢出的原因之一;內存泄露積累起來將導致內存溢出。
2) 內存泄露可以通過完善代碼來避免;內存溢出可以通過調整配置來減少發生頻率,但無法徹底避免。

四、如何避免內存泄漏、溢出

  1. 儘早釋放無用對象的引用。
    好的辦法是使用臨時變量的時候,讓引用變量在退出活動域後自動設置爲null,暗示垃圾收集器來收集該對象,防止發生內存泄露。

  2. 程序進行字符串處理時,儘量避免使用String,而應使用StringBuffer。因爲每一個String對象都會獨立佔用內存一塊區域,如:

    String str = "aaa";    
    String str2 = "bbb";    
    String str3 = str + str2;    
    // 假如執行此次之後str , str2再不被調用,那麼它們就會在內存中等待GC回收;    
    // 假如程序中存在過多的類似情況就會出現內存錯誤;   
    
  3. 儘量少用靜態變量。
    因爲靜態變量是全局的,GC不會回收。

  4. 避免集中創建對象尤其是大對象,如果可以的話儘量使用流操作。因爲
    JVM會突然需要大量內存,這時會觸發GC優化系統內存環境;

  5. 儘量運用對象池技術以提高系統性能。
    生命週期長的對象擁有生命週期短的對象時容易引發內存泄漏,例如大集合對象擁有大數據量的業務對象的時候,可以考慮分塊進行處理,然後解決一塊釋放一塊的策略。

  6. 不要在經常調用的方法中創建對象,尤其是忌諱在循環中創建對象。
    可以適當的使用hashtable,vector 創建一組對象容器,然後從容器中去取那些對象,而不用每次new之後又丟棄。

  7. 優化配置

     1、 設置-Xms、-Xmx相等;
     2、 設置NewSize、MaxNewSize相等;
     3、 設置Heap size, PermGen space:
     	 Tomcat 的配置示例:修改 %TOMCAT_HOME%/bin/catalina.bat or catalina.sh
          在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:
         set JAVA_OPTS=-Xms800m -Xmx800m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m 
    

更多的配置,可以參考另一篇文章:https://blog.csdn.net/LeegooWang/article/details/88696195

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章