記憶體洩漏
記憶體洩漏是指程式在申請記憶體後,無法釋放已申請的記憶體空間,無用物件(不再使用的物件)持續佔有記憶體或無用物件的記憶體得不到及時釋放,從而造成記憶體空間的浪費。記憶體洩漏最終會導致OOM。
造成記憶體洩漏典型場景:
1. 單例模式的不正確使用單例物件在初始化後將在JVM的整個生命週期中以靜態變數的方式存在。如果單例物件持有對外部物件的引用,那麼這個物件將不能被JVM正常回收
2. 資料庫、網路、IO連線沒有被關閉釋放這類連線,一般會提供close方法進行顯式關閉。但如果沒有進行close,是不會自動被gc回收的。3.不合適的物件引用
比如,生命週期長的物件持有生命週期短的物件的引用就很容易造成記憶體洩漏,儘管生命週期短的物件已經不再需要,但是因為生命週期長的物件持有對它的引用而導致不能被回收。
記憶體溢位
記憶體溢位即out of memory簡稱OOM。當程式申請記憶體時,沒有足夠的記憶體空間供其使用,往往會出現OOM。比如申請了一個Integer,但給它存了Long型別才能存下的數,那就會導致記憶體溢位。
堆外記憶體
關於堆內記憶體以及相應的記憶體回收策略,在之前的文章《JVM記憶體管理和垃圾回收》、《JVM垃圾回收器、記憶體分配與回收策略》中已有介紹。對於堆外記憶體是指分配的物件直接受作業系統管理的JVM記憶體堆以外的空間。同時因為這部分割槽域直接受作業系統的管理,別的程式可以直接通過作業系統對其進行訪問,減少了從JVM中複製資料的過程。
堆外記憶體適用生命週期較長的物件,具有以下特點:
- 可以很方便的自主開闢很大的記憶體空間,對於大記憶體有良好的伸縮性
- 減少垃圾回收帶來的系統停頓時間
- 在程式間可以共享物件,減少JVM間的複製過程
- 適合那些分配次數少,讀寫操作頻繁的場景
但也存在如下缺點:
- 容易出現記憶體洩漏,並且很難排查
-
堆外記憶體的資料結構不直觀,當儲存結構複雜的物件時,會浪費大量的時間對其進行序列化
常用JVM配置引數
-Xms:JVM初始最小堆記憶體
-Xmx:JVM允許最大堆記憶體
-XX:PermSize:JVM初始非堆記憶體
-XX:MaxPermSize:JVM允許最大的非堆記憶體
-XX:+UseConcMarkSweepGC:年老代啟用CMS收集器,可以儘量減少fullGC
-XX:+UseParNewGC:設定年輕代為多執行緒並行收集
-XX:+UseCMSCompactAtFullCollection:在full gc時,對老年代的壓縮(CMS的時候,會導致記憶體碎片,使記憶體空間不連續,可能會影響效能,但是可以消除碎片)
-XX:CMSInitiatingOccupancyFraction:當老年代被佔用空間達到一定比例時觸發CMS垃圾收集
-Xverify:none:類載入的時候關閉位元組碼驗證
-XX:+DisableExplicitGC:告訴JVM關掉System.gc
-XX:+CMSParallelRemarkEnabled:再標記演算法,降低標記停頓時間
-XX:+PrintHeapAtGC:列印GC前後的詳細堆疊資訊,主要用於生產環境或者壓力測試時候看的資訊
-XX:+PrintGCTimeStamps:輸出GC的時間戳
-XX:PretenureSizeThreshold:使大物件直接進入老年代
關聯文章:
關注微信公眾號:大資料學習與分享,獲取更對技術乾貨