java問題之2:JVM堆外內存問題排查--刪除


首先確認堆占用

jmap 查看heap內存使用情況

jmap -heap pid
1

可以查看到MetaspaceSize,CompressedClassSpaceSize,MaxMetaSize
jmap和jdk版本有關系,有些jdk版本會查看不到內存信息,可以使用jstat來查看統計信息

jstat 收集統計信息

jstat -gc pid 1000

1

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

1

在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

1

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

1

可以結合pmap,和nmt得到內存地址空間。和堆外占用情況了

接下來需要做的就是分析堆外內存的內容了。
gdb dump查看內存空間內容

(gdb) dump binary memory ./file BEGIN_ADDRESS END_ADDRESS

1

將內存內容dump到文件中,就可以查看到文件中的內容了。
但是這種方式不直觀,所以可以使用其他工具

gperf
google的,使用gperf2.5即可,網上很多安裝都說一定要安裝libunwind,其實都是瞎抄抄,老版本確實需要,2.5的版本不需要了。

https://blog.csdn.net/unix21/article/details/79161250
另外一個注意點就是雖然heap文件只有1M,但是可以分析出堆外內存的大小。
不過我在實際使用過程中,gperf並沒有分析出實際的堆外內存情況,通過pmap可以看出堆外內存占用有幾個G,但是gperf始終只有200M

Jemalloc
https://github.com/jemalloc/jemalloc/releases
安裝

./configurate –enable-prof
make
sudo make install
1
2
3

配置

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

1
2

https://github.com/jemalloc/jemalloc/wiki/Getting-Started

最后分析是dubbo,rpc調用過程中,有很多的數據傳輸對象,而堆外內存大小又沒有限制,導致內存持續飆高


免責聲明!

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



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