
1. 通用規則
1.1. 不要假設問題出在堆空間
1.2. 謹慎地創建物件并盡快丟棄它們
1.3. 使用更少的記憶體是提高垃圾回收器效率最好的辦法
1.3.1. 減少記憶體使用是一個重要的目標
1.3.2. 和大多數性能優化主題一樣,將精力集中于最大化利用現有記憶體會更有幫助
1.4. 物件重用方式
1.4.1. 執行緒區域變數
1.4.2. 特殊物件參考
1.4.3. 物件池
1.5. 重用物件意味著它們將長期存在并會影響垃圾回收器
1.5.1. 當它們被合理地重用時,整體性能將得到提升
2. 堆直方圖
2.1. heap histogram
2.2. 快速查看應用程式中物件數量的方法,不需要生成完整堆轉儲
2.3. 用于識別由于某種特定型別的物件創建得太多而導致的記憶體問題
2.4. % jmap -histo process_id
2.5. % jmap -histo:live process_id
3. 堆轉儲
3.1. heap dump
3.2. 最強大的跟蹤記憶體使用的技術
3.3. 常用工具
3.3.1. jvisualvm
3.3.1.1. 從正在運行的程式中獲得堆轉儲檔案
3.3.1.2. 可以打開之前生成的堆轉儲檔案
3.3.1.3. 檢查最大的保留物件并執行對堆的任意查詢
3.3.2. 開源的Eclipse Memory Analyzer Tool
3.3.2.1. mat
3.3.2.2. 加載一個或者多個堆轉儲檔案并對其進行分析
3.3.2.3. 可以產生報告
3.3.2.4. 可以用來瀏覽堆
3.3.2.5. 對堆執行類似SQL的查詢
3.3.2.6. 提示可能出現問題的地方
3.4. % jcmd process_id GC.heap_dump /path/to/heap_dump.hprof
3.5. % jmap -dump:live,file=/path/to/heap_dump.hprof process_id
3.5.1. 包含live選項會在堆被轉儲之前強制執行Full GC
3.5.2. 如果因為某些原因你想包含其他的物件(死物件),可以在jcmd命令列的末尾加上-all
4. 記憶體分析
4.1. 物件的淺大小(shallow size)
4.1.1. 物件本身的大小
4.2. 物件的深大小(deep size)
4.2.1. 包含它所參考的物件的大小
4.3. 物件的深大小和保留大小的區別在于其參考的物件是否是共享的
4.4. 保留大量堆空間的物件通常被稱為堆的支配者
4.5. 一般的經驗法則是,尋找路徑應該從集合物件(如HashMap)而不是從條目(如HashMap$Entry)開始,并且要尋找最大的集合
5. 記憶體溢位錯誤
5.1. out-of-memory
5.2. JVM沒有可用的原生記憶體
5.2.1. 在Linux中,用戶常常只被允許創建1024個行程
5.2.1.1. 可以通過運行ulimit-u來檢查這個值
5.2.1.2. 試圖創建第1025個執行緒,JVM就會拋出OutOfMemoryError例外
5.2.1.3. 作業系統對行程數量施加的限制導致的錯誤
5.2.2. 錯誤訊息
5.2.2.1. Exception in thread "main" java.lang.OutOfMemoryError:unable to create new native thread
5.3. 元空間記憶體不足
5.3.1. 這個錯誤的發生通常是因為你設定了最大大小
5.3.1.1. 元空間默認情況下沒有最大大小的限制
5.3.2. 根本原因
5.3.2.1. 分配的元空間已經放不下應用程式使用的類
5.3.2.2. 涉及類加載器的記憶體泄漏
5.3.2.2.1. 最常發生在動態加載類的服務器中
5.3.2.2.1.1. 增加元空間的大小會有幫助,但也只是推遲了錯誤發生的時間而已
5.3.2.2.1.2. 除了聯系應用服務器廠商讓他們修復記憶體泄漏問題之外,沒有其他辦法
5.3.3. 錯誤訊息
5.3.3.1. Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
5.4. Java堆本身記憶體不足
5.4.1. 對于給定大小的堆,應用程式已經無法創建任何額外的物件
5.4.2. 錯誤訊息
5.4.2.1. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
5.5. -XX:+HeapDumpOnOutOfMemoryError
5.5.1. 打開這個標志會讓JVM在拋出記憶體溢位錯誤時創建堆轉儲
5.5.2. 默認是false
5.6. -XX:HeapDumpPath=
5.6.1. 該標志指定堆轉儲的寫入位置
5.6.1.1. 可以指定目錄
5.6.1.1.1. 會使用默認檔案名
5.6.1.2. 可以指定要生成的實際檔案名
5.6.2. 默認位置是應用程式當前作業目錄下的java_pid.hprof
5.7. -XX:+HeapDumpAfterFullGC
5.7.1. 運行Full GC之后生成堆轉儲
5.8. -XX:+HeapDumpBeforeFullGC
5.8.1. 運行Full GC之前生成堆轉儲
5.9. -XX:+ExitOnOutOfMemoryError
5.9.1. JVM在堆記憶體用盡時退出
5.9.2. 默認是false
5.10. JVM花費了太多時間執行GC
5.10.1. 錯誤訊息
5.10.1.1. Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
5.11. -XX:GCTimeLimit=N
5.11.1. 在Full GC中花費的時間超過了指定值
5.11.2. 默認值是98
5.11.2.1. 98%的時間花在GC上,該條件就滿足
5.12. -XX:GCHeapFreeLimit=N
5.12.1. 一次Full GC回收的記憶體量小于指定值
5.12.2. 默認值是2
5.12.2.1. Full GC期間回收的記憶體小于堆的2%,該條件就滿足
5.13. -XX:+UseGCOverheadLimit
5.13.1. 前面兩個條件在5個連續的Full GC周期中都成立
5.13.2. 默認值true
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/546278.html
標籤:其他
上一篇:盤點10個最受歡迎IntelliJ IDEA主題,必有一款適合你!
下一篇:三天吃透Kafka面試八股文
