JVM堆外記憶體問題排查
摘要
JVM 堆記憶體一般分析的比較多,本篇談談堆外記憶體問題排查,通常我們需要排查堆外記憶體的原因是系統整個記憶體使用飆高,但是堆內記憶體使用正常。這時候就需要分析堆外記憶體了
堆外記憶體組成
通常JVM的引數我們會配置
-Xms 堆初始記憶體
-Xmx 堆最大記憶體
-XX:+UseG1GC/CMS 垃圾回收器
-XX:+DisableExplicitGC 禁止顯示GC
-XX:MaxDirectMemorySize 設定最大堆外記憶體,預設是-xmx-survivor,也就是基本上和-xmx大小相等
-Xss:每個執行緒的堆疊大小,預設1M
-Xmn: 年輕代大小(eden區+2 survivor)
-XX:newRatio: 4 年輕代與老年代1:4
-XX:survivorRatio: 8Eden區與survivor大小比值
java整個程式佔用的記憶體:
- 堆記憶體
- metaspace(堆內) JDK8使用metaspace來替代了permsize:永久代大小
- 堆外記憶體使用
- 執行緒棧空間
堆外記憶體回收: 堆外記憶體的回收是通過system.gc()來的,依賴於目前的gc機制。
通常是通過DirectByteBuffer物件來分配堆外記憶體,gc的時候就是判斷這個物件是否被引用,來決定是否回收。
問題排查
首先確認堆佔用
jmap 檢視heap記憶體使用情況
jmap -heap pid
可以檢視到MetaspaceSize,CompressedClassSpaceSize,MaxMetaSize
jmap和jdk版本有關係,有些jdk版本會檢視不到記憶體資訊,可以使用jstat來檢視統計資訊jstat 收集統計資訊
jstat -gc pid 1000
S0C/S0U | S1C/S1U | EC/EU | CCSC/CCSU | YGC/YGCT | FGC/FCGT | GCT |
---|---|---|---|---|---|---|
survivor0容量和使用 | survivor1容量和使用 | Eden | jdk8是meta,以前應該是PC,PC | young gc次數和耗時 | full gc次數和耗時 | total gc時間 |
排除掉heap的問題
分析堆外情況
NMT(native memory tracking)
使用
在JVM引數中新增
-XX:NativeMemoryTracking=[off | summary | detail]
-XX:NativeMemoryTracking=detail
在JVM執行過程中,使用jcmd獲取相關資訊
jcmd pid VM.native_memory [summary | detail | baseline | summary.diff | detail.diff | shutdown] [scale= KB | MB | GB]
jcmd pid VM.native_memory detail
baseline個基準,之後會輸出diff引數,來和這個基線版本進行比較,可以兩次的記憶體差
NMT報告會顯示記憶體使用情況
類別 | 含義 |
---|---|
Java Heap | 堆大小 |
Thread | 執行緒 |
Thread Stack | 執行緒棧 |
更多參考:
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr022.html
NMT可以得到執行緒棧大小,排除棧空間影響
pmap 檢視程式記憶體地址空間
pmap -x pid | sort xx
可以結合pmap,和nmt得到記憶體地址空間。和堆外佔用情況了
接下來需要做的就是分析堆外記憶體的內容了。
gdb dump檢視記憶體空間內容
(gdb) dump binary memory ./file BEGIN_ADDRESS END_ADDRESS
將記憶體內容dump到檔案中,就可以檢視到檔案中的內容了。
但是這種方式不直觀,所以可以使用其他工具
gperf
google的,使用gperf2.5即可,網上很多安裝都說一定要安裝libunwind,其實都是瞎抄抄,老版本確實需要,2.5的版本不需要了。https://blog.csdn.net/unix21/article/details/79161250
另外一個注意點就是雖然heap檔案只有1M,但是可以分析出堆外記憶體的大小。
不過我在實際使用過程中,gperf並沒有分析出實際的堆外記憶體情況,通過pmap可以看出堆外記憶體佔用有幾個G,但是gperf始終只有200MJemalloc
https://github.com/jemalloc/jemalloc/releases
安裝./configurate –enable-prof make sudo make install
配置
export LD_PRELOAD=/usr/local/lib/libjemalloc.so
export MALLOC_CONF=prof:true,lg_prof_interval:31,lg_prof_sample:17,prof_prefix:/output/jeprof
最後分析是dubbo,rpc呼叫過程中,有很多的資料傳輸物件,而堆外記憶體大小又沒有限制,導致記憶體持續飆高
參考
https://www.cnblogs.com/softidea/p/5267757.html
https://blog.csdn.net/u014459326/article/details/53609885
https://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html
http://lovestblog.cn/blog/2015/05/07/system-gc/
https://blog.csdn.net/kringpin_lin/article/details/26211119
https://blog.csdn.net/jicahoo/article/details/50933469
http://tinylab.org/the-builtin-heap-profiling-of-jemalloc/
相關文章
- java 堆外記憶體排查Java記憶體
- JAVA堆外記憶體排查小結Java記憶體
- netty 堆外記憶體洩露排查盛宴Netty記憶體洩露
- jvm 堆記憶體JVM記憶體
- 記一次堆外記憶體洩漏排查過程記憶體
- JVM 常見線上問題 → CPU 100%、記憶體洩露 問題排查JVM記憶體洩露
- JVM執行緒和記憶體溢位問題排查思路JVM執行緒記憶體溢位
- 關於JVM堆外記憶體的一切JVM記憶體
- 使用mtrace追蹤JVM堆外記憶體洩露JVM記憶體洩露
- JVM堆記憶體詳解JVM記憶體
- 排查Java的記憶體問題Java記憶體
- JVM原始碼分析之堆外記憶體完全解讀JVM原始碼記憶體
- 一次尋常的堆外記憶體洩漏排查記憶體
- JVM 堆記憶體設定原理JVM記憶體
- eclipse設定JVM記憶體堆EclipseJVM記憶體
- redisson記憶體洩漏問題排查Redis記憶體
- 從記憶體洩露、記憶體溢位和堆外記憶體,JVM優化引數配置引數記憶體洩露記憶體溢位JVM優化
- jvm堆記憶體和GC簡介JVM記憶體GC
- 探索JVM的垃圾回收(堆記憶體)JVM記憶體
- 【JVM故障問題排查心得】「記憶體診斷系列」JVM記憶體與Kubernetes中pod的記憶體、容器的記憶體不一致所引發的OOMKilled問題總結(上)JVM記憶體OOM
- 【JVM故障問題排查心得】「記憶體診斷系列」JVM記憶體與Kubernetes中pod的記憶體、容器的記憶體不一致所引發的OOMKilled問題總結(下)JVM記憶體OOM
- 分散式 | 令人頭疼的堆外記憶體洩露怎麼排查?分散式記憶體洩露
- Java堆外直接記憶體回收Java記憶體
- 【JVM之記憶體與垃圾回收篇】堆JVM記憶體
- Spring Boot引起的“堆外記憶體洩漏”排查及經驗總結Spring Boot記憶體
- [效能]【JVM】關於JVM記憶體的N個問題JVM記憶體
- 模擬實戰排查堆記憶體溢位(java.lang.OutOfMemoryError: Java heap space)問題記憶體溢位JavaError
- 【JVM】堆體系結構及其記憶體調優JVM記憶體
- project中的堆疊記憶體,記憶體地址引用,gc相關問題Project記憶體GC
- Linux排查JVM問題LinuxJVM
- 解Bug之路-記一次JVM堆外記憶體洩露Bug的查詢JVM記憶體洩露
- 故障分析 | 租戶 memstore 記憶體滿問題排查記憶體
- 面試題:JVM在Java堆中對物件的建立、記憶體結構、訪問方式面試題JVMJava物件記憶體
- Java直接(堆外)記憶體使用詳解Java記憶體
- Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)RedisError記憶體溢位
- JVM面試問題系列:深入詳解JVM 記憶體區域及記憶體溢位分析JVM面試記憶體溢位
- 記一次堆外記憶體洩漏分析記憶體
- 如何解決JVM OutOfMemoryError記憶體洩漏問題?JVMError記憶體