1. 程式人生 > 其它 >JVM診斷及工具筆記(4) 使用visualvm分析JVM堆記憶體洩漏

JVM診斷及工具筆記(4) 使用visualvm分析JVM堆記憶體洩漏

在這裡感謝最近一直閱讀我文章的小夥伴,如果覺得文章對你有用,可以幫忙關注轉載,需要的時候可以及時找到文章。

背景

今年Q3季度我們在推廣業務方使用Iceberg,當時為了讓不同業務線的使用者可以使用自己的hadoop賬號許可權把資料寫到他們的hadoop集市目錄,我們在Iceberg中添加了ugi,使Flink賬號代理成業務方的hadoop賬號。這次的堆記憶體洩漏就是因為我們使用ugi錯誤方式引發的。

現象

通過監控,我們發現使用者的Flink寫Iceberg任務的堆記憶體呈增長趨勢,沒多久就報堆記憶體oom了。

定位過程

1.列印日誌及設定oom時dump堆記憶體到磁碟

clusterConf.env.java.opts=-XX:+PrintGCDetails

-XX:+PrintGCDateStamps -Xloggc:${LOG_DIRS}/gc.log -XX:+HeapDumpOnOutOfMemoryError

-XX:HeapDumpPath=/tmp/${CONTAINER_ID}.dump

2.使用visualvm分析堆記憶體檔案 (一定要計算物件保留大小有助於分析)

發現最多的例項竟然是Entry物件,開始去分析其引用(主要是想查詢找有沒有比較大的HashMap),

​ 如下圖好多引用都是DistributedFileSystem引用的DFSclient物件。

搜下DFSClient物件,發現其數量有16000多個。DFSClient物件為什麼會這麼多,繼續往下跟發現其被快取到DistributedFileSystem的cache裡面。

​ cache中具體快取使用的key如圖 scheme, authority,ugi,unique 其中unique可以忽略,在visualvm上看都是相同的,scheme及authority記錄著幾個namenode的地址,值也並不多,唯一異常的就是存在超大量的ugi物件,此時記憶體洩漏的真凶差不多找到了。

發現在改造的Iceberg支援代理使用者的程式碼中,每次呼叫getFs方法都要重新建立一個ugi物件。

解決

ugi按使用者快取起來之後,cache裡面的DFSClient物件數量就符合預期了。這個任務就再也沒有發生過堆記憶體洩漏了。