日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 监控 native 内存_JVM NativeMemoryTracking 分析堆外内存泄露

發布時間:2023/12/2 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 监控 native 内存_JVM NativeMemoryTracking 分析堆外内存泄露 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Native Memory Tracking (NMT) 是Hotspot VM用來分析VM內部內存使用情況的一個功能。我們可以利用jcmd(jdk自帶)這個工具來訪問NMT的數據。

NMT介紹

工欲善其事必先利其器,我們先把相關需要的配置和工具介紹清楚,再通過例子來看看具體如何使用NMT。

打開NMT

NMT必須先通過VM啟動參數中打開,不過要注意的是,打開NMT會帶來5%-10%的性能損耗。

-XX:NativeMemoryTracking=[off | summary | detail]

# off: 默認關閉

# summary: 只統計各個分類的內存使用情況.

# detail: Collect memory usage by individual call sites.

jcmd查看NMT報告

通過jcmd查看NMT報告以及查看對比情況。

jcmd VM.native_memory [summary | detail | baseline | summary.diff | detail.diff | shutdown] [scale= KB | MB | GB]

# summary: 分類內存使用情況.

# detail: 詳細內存使用情況,除了summary信息之外還包含了虛擬內存使用情況。

# baseline: 創建內存使用快照,方便和后面做對比

# summary.diff: 和上一次baseline的summary對比

# detail.diff: 和上一次baseline的detail對比

# shutdown: 關閉NMT

VM退出時打印NMT

可以通過下面VM參數在JVM退出時打印NMT報告。

-XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics

NMT實戰

癥狀

某個服務(C)在客戶環境使用后發現其內存占用不斷變大且遠超Xmx指定的大小,導致整個系統因缺少內存造成其他服務無法啟動。當時查看到其RSS大約為11G,-Xmx=6G而且heap利用率不到50%。

user@hostxxx> prstat -p 2780

PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/NLWP

2780 user 11G 11G sleep 59 0 44:16:39 0.0% java/196

user@hostxxx> /opt/jdk1.8.0_40/bin/jstat -gcutil 2780

S0 S1 E O M CCS YGC YGCT FGC FGCT GCT

0.00 100.00 90.60 46.80 98.02 97.10 11323 4049.745 11 225.345 4275.090

分析

服務通過-Xmx=6G指定最大堆分配為6G,但實際RSS已達到11G,開始懷疑堆外內存是否有內存泄露。為了有更好詳細的數據,就在本地重現這個問題,并且打開了NMT持續監控。

NMT的Report如下,重點關注每個分類下的commit大小,這個是實際使用的內存大小。

6739: #進程ID

Native Memory Tracking:

Total: reserved=8491110KB, committed=7220750KB

- Java Heap (reserved=6293504KB, committed=6291456KB)

(mmap: reserved=6293504KB, committed=6291456KB)

- Class (reserved=1107429KB, committed=66189KB)

(classes #11979)

(malloc=1509KB #18708)

(mmap: reserved=1105920KB, committed=64680KB)

- Thread (reserved=159383KB, committed=159383KB)

(thread #156)

(stack: reserved=158720KB, committed=158720KB)

(malloc=482KB #788)

(arena=182KB #310)

- Code (reserved=255862KB, committed=41078KB)

(malloc=6262KB #9319)

(mmap: reserved=249600KB, committed=34816KB)

- GC (reserved=449225KB, committed=449225KB)

(malloc=166601KB #1714646)

(mmap: reserved=282624KB, committed=282624KB)

- Compiler (reserved=395KB, committed=395KB)

(malloc=265KB #856)

(arena=131KB #3)

- Internal (reserved=146041KB, committed=146041KB)

(malloc=132185KB #276370)

(mmap: reserved=13856KB, committed=13856KB)

- Symbol (reserved=31487KB, committed=31487KB)

(malloc=29209KB #91080)

(arena=2278KB #1)

- Native Memory Tracking (reserved=33212KB, committed=33212KB)

(malloc=168KB #2575)

(tracking overhead=33044KB)

- Arena Chunk (reserved=2284KB, committed=2284KB)

(malloc=2284KB)

- Unknown (reserved=12288KB, committed=0KB)

(mmap: reserved=12288KB, committed=0KB)

Virtual memory map:

......

并且在服務器上通過cron job來定期抓取NMT的report保存下來做分析,而且同時也把其對應的RSS和PMAP都抓取了一份。

COLLECTOR_PID=`ps -ef|grep "ProcessName" | grep -v grep | awk '{print $2}'`

OUTDIR=/opt/chkmem

HOSTNAME=`hostname`

prstat -s rss 1 1 > ${OUTDIR}/${HOSTNAME}_coll_${COLLECTOR_PID}_prstat_`date '+%Y%m%d_%H%M%S'`.txt

/opt/jdk1.8.0_40/bin/jcmd ${COLLECTOR_PID} VM.native_memory detail > ${OUTDIR}/${HOSTNAME}_coll_${COLLECTOR_PID}_nmd_`date '+%Y%m%d_%H%M%S'`.txt

pmap -x ${COLLECTOR_PID} > ${OUTDIR}/${HOSTNAME}_coll_${COLLECTOR_PID}_pmap_`date '+%Y%m%d_%H%M%S'`.txt

分析發現NMT中的Symbol域持續增大,從最開始的幾十兆已經增加到了2G左右,而且整個jvm的內存使用量也在持續增加。見下圖:

驗證后發現問題和JDK8的bug https://bugs.java.com/view_bug.do?bug_id=8180048 非常類似,測試后也證實確實如此,最后通過升級JDK解決了這個問題。 導致這個問題的組件是Jackson Streaming API 中的 JsonFactory.Feature.INTERN_FIELD_NAMES 引起的,由于項目中需要大量解析動態json文件,并且key都被intern到JVM native 內存無法釋放導致內存泄露。

總結

以上是生活随笔為你收集整理的java 监控 native 内存_JVM NativeMemoryTracking 分析堆外内存泄露的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。