服務器內存溢出問題


 

系統測試時,導出、下載功能,偶爾會出現“out of memory”(內存溢出)問題。

內存溢出是指應用系統中存在無法回收的內存或使用的內存過多,最終使得程序運行要用到的內存大於虛擬機能提供的最大內存。

   引起內存溢出的原因有很多種,常見的有以下幾種:
  1.內存中加載的數據量過於龐大,如一次從數據庫取出過多數據;
  2.集合類中有對對象的引用,使用完后未清空,使得JVM不能回收;
  3.代碼中存在死循環或循環產生過多重復的對象實體;
  4.使用的第三方軟件中的BUG;
  5.啟動參數內存值設定的過小;

內存溢出的解決方案
      第一步,修改JVM啟動參數,直接增加內存。(-Xms,-Xmx參數一定不要忘記加。)

  第二步,檢查錯誤日志,查看“OutOfMemory”錯誤前是否有其它異常或錯誤。

  第三步,對代碼進行走查和分析,找出可能發生內存溢出的位置。

重點排查以下幾點:
  1.檢查對數據庫查詢中,是否有一次獲得全部數據的查詢。一般來說,如果一次取十萬條記錄到內存,就可能引起內存溢出。這個問題比較隱蔽,在上線前,數據庫中數據較少,不容易出問題,上線后,數據庫中數據多了,一次查詢就有可能引起內存溢出。因此對於數據庫查詢盡量采用分頁的方式查詢。
  2.檢查代碼中是否有死循環或遞歸調用。 

  3.檢查是否有大循環重復產生新對象實體。 

  4.檢查對數據庫查詢中,是否有一次獲得全部數據的查詢。一般來說,如果一次取十萬條記錄到內存,就可能引起內存溢出。這個問題比較隱蔽,在上線前,數據庫中   數據較少,不容易出問題,上線后,數據庫中數據多了,一次查詢就有可能引起內存溢出。因此對於數據庫查詢盡量采用分頁的方式查詢。 

  5.檢查List、MAP等集合對象是否有使用完后,未清除的問題。List、MAP等集合對象會始終存有對對象的引用,使得這些對象不能被GC回收。

  第四步,使用內存查看工具動態查看內存使用情況

如何解決內存溢出的問題,接下來以tomcat服務器為例:

我們首先得找到內存管理所要設置的參數在哪個文件:<CATALINA_HOME>/bin/catalina.bat。

需要添加一行代碼:

JAVA_OPTS="-Xms512m-Xmx512m -Xss1024K -XX:PermSize=256m -XX:MaxPermSize=256m"

下面分別對各參數進行介紹和解釋:

JVM 相關參數:

參數名參數說明

-server 啟用能夠執行優化的編譯器, 顯著提高服務器的性能,但使用能夠執行優化的編譯器時,服務器的預備時間將會較長。生產環境的服務器強烈推薦設置此參數。

-Xss 單個線程堆棧大小值;JDK5.0 以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K。在相同物理內存下,減小這個值能生成更多的線程。但是操作系統對一個進程內的線程數還是有限制的,不能無限生成,經驗值在3000~5000左右。

-XX:+UseParNewGC 可用來設置年輕代為並發收集【多CPU】,如果你的服務器有多個CPU,你可以開啟此參數;開啟此參數,多個CPU 可並發進行垃圾回收,可提高垃圾回收的速度。此參數和+UseParallelGC,-XX:ParallelGCThreads搭配使用。

+UseParallelGC 選擇垃圾收集器為並行收集器。此配置僅對年輕代有效。即上述配置下,年輕代使用並發收集,而年老代仍舊使用串行收集。可提高系統的吞吐量。

-XX:ParallelGCThreads 年輕代並行垃圾收集的前提下(對並發也有效果)的線程數,增加並行度,即:同時多少個線程一起進行垃圾回收。此值最好配置與處理器數目相等。永久存儲區相關參數:參數名參數說明

-Xnoclassgc 每次永久存儲區滿了后一般GC 算法在做擴展分配內存前都會觸發一次FULL GC,除非設置了-Xnoclassgc.

-XX:PermSize 應用服務器啟動時,永久存儲區的初始內存大

-XX:MaxPermSize 應用運行中,永久存儲區的極限值。為了不消耗擴大JVM 永久存儲區分配的開銷,將此參數和-XX:PermSize這個兩個值設為相等。堆空間相關參數參數名參數說明

-Xms 啟動應用時,JVM 堆空間的初始大小值。

-Xmx 應用運行中,JVM 堆空間的極限值。為了不消耗擴大JVM 堆控件分配的開銷,將此參數和-Xms 這個兩個值設為相等,考慮到需要開線程,講此值設置為總內存的80%.

-Xmn 此參數硬性規定堆空間的新生代空間大小,推薦設為堆空間大小的1/4。

上面所列的JVM 參數關系到系統的性能,而其中-XX:PermSize,

-XX:MaxPermSize,-Xms,-Xmx 和-Xmn 這5 個參數更是直接關系到系統的性能,系統是否會出現內存溢出。

-XX:PermSize 和-XX:MaxPermSize 分別設置應用服務器啟動時,永久存儲區的初始大小和極限大小;在生成環境中強烈推薦將這個兩個值設置為相同的值,以避免分配永久存儲區的開銷,具體的值可取系統“疲勞測試”獲取到的永久存儲區的極限值;如果不進行設置-XX:MaxPermSize 默認值為64M,一般來說系統的類定義文件大小都會超過這個默認值。

-Xms 和-Xmx 分別是服務器啟動時,堆空間的初始大小和極限值。-Xms的默認值是物理內存的1/64 但小於1G,-Xmx 的默認值是物理內存的1/4 但小於1G.在生產環境中這些默認值是肯定不能滿足我們的需要的。也就是你的服務器有8g 的內存,不對JVM 參數進行設置優化,應用服務器啟動時還是按默認值來分配和約束JVM 對內存資源的使用,不會充分的利用所有的內存資源。

 

結論:“永久存儲區溢出(java.lang.OutOfMemoryError:Java Permanent Space)”乃是永久存儲區設置太小,不能滿足系統需要的大小,此時只需要調整-XX:PermSize 和-XX:MaxPermSize 這兩個參數即可。“JVM 堆空間溢出(java.lang.OutOfMemoryError: Java heap space)”錯誤是JVM 堆空間不足,此時只需要調整-Xms 和-Xmx 這兩個參數即可。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM