問題
druid監控sql在網頁端顯示,我的服務插入sql比較大,druid把執行過的sql保存在DruidDataSource類的成員變量JdbcDataSourceStat dataSourceStat;
JdbcDataSourceStat類中的LinkedHashMap<String, JdbcSqlStat> ?sqlStatMap中;?sqlStatMap中的sql越來越多導致老年區的內存越來越多且回收不掉。
解決辦法
關閉druid的監控,該監控會耗盡內存?
spring.datasource.druid.stat-view-servlet.enabled=false?
spring.datasource.druid.web-stat-filter.enabled=false?# 配置監控統計攔截的filters,去掉后監控界面sql無法統計,'wall'用于防火墻
# ? ? ? ?filters: stat,wall,slf4j? ? 原來的配置filters: slf4j? ? ?#現在的配置,除去stat,wall
發現問題
2025-04-27T02:04:58.124+0800: 118542.443: [Full GC (Ergonomics) [PSYoungGen: 389120K->389119K(427520K)] [ParOldGen: 1747632K->1747631K(1747968K)] 2136752K->2136751K(2175488K), [Metaspace: 91767K->91767K(1136640K)], 0.4695953 secs] [Times: user=1.64 sys=0.00, real=0.47 secs]
2025-04-27T02:04:58.593+0800: 118542.914: [Full GC (Ergonomics) [PSYoungGen: 389120K->389119K(427520K)] [ParOldGen: 1747631K->1747631K(1747968K)] 2136751K->2136751K(2175488K), [Metaspace: 91767K->91767K(1136640K)], 0.4865868 secs] [Times: user=1.48 sys=0.02, real=0.49 secs]
2025-04-27T02:04:59.082+0800: 118543.402: [Full GC (Ergonomics) [PSYoungGen: 389119K->389119K(427520K)] [ParOldGen: 1747635K->1747629K(1747968K)] 2136755K->2136749K(2175488K), [Metaspace: 91767K->91767K(1136640K)], 0.4742007 secs] [Times: user=1.52 sys=0.00, real=0.47 secs]
2025-04-27T02:04:59.557+0800: 118543.877: [Full GC (Ergonomics) [PSYoungGen: 389120K->389119K(427520K)] [ParOldGen: 1747629K->1747629K(1747968K)] 2136749K->2136749K(2175488K), [Metaspace: 91767K->91767K(1136640K)], 0.4986030 secs] [Times: user=1.55 sys=0.02, real=0.50 secs]
2025-04-27T02:05:00.057+0800: 118544.377: [Full GC (Ergonomics) [PSYoungGen: 389120K->389119K(427520K)] [ParOldGen: 1747629K->1747629K(1747968K)] 2136749K->2136749K(2175488K), [Metaspace: 91767K->91767K(1136640K)], 0.4815433 secs] [Times: user=1.63 sys=0.00, real=0.48 secs]
2025-04-27T02:05:00.539+0800: 118544.859: [Full GC (Ergonomics) [PSYoungGen: 389119K->389119K(427520K)] [ParOldGen: 1747629K->1747629K(1747968K)] 2136749K->2136749K(2175488K), [Metaspace: 91767K->91767K(1136640K)], 0.4686810 secs] [Times: user=1.53 sys=0.00, real=0.47 secs]
這個GC日志顯示Full GC沒有釋放任何堆內存空間,還一直在執行Full GC,導致cpu占用在80%,可能是存在內存泄漏問題導致對象無法被回收。
找出問題根源
1.導出dump文件
方式一:?jmap -dump:format=b,file=D:\work_temp\1\shdhv3.hprof 20920
20920=pid
方式二:運行C:\Program Files\Java\jdk1.8.0_171\bin\jvisualvm.exe
選中運行的jar應用程序--》堆Dump(H) -->在下面生成heapdump文件--》右鍵--》另存為--》選擇路徑
2.下載安裝mat
MemoryAnalyzer工具是Eclipse內存分析器是一種快速、功能豐富的java堆分析器,可以幫助你找到內存泄漏和減少內存消耗,比jdk自帶的工具強大很多。
下載地址:
https://eclipse.dev/mat/
mat需要至少jdk17版本,我的只有jdk1.8,下載jdk17安裝后把jdk-17的文件夾直接拷貝到MemoryAnalyzer-1.16.1.20250109-win32.win32.x86_64\mat路徑下
指定jdk17路徑,修改MemoryAnalyzer.ini文件,在文件內容的最前面添加指定
-vm
D:\常用軟件\MemoryAnalyzer-1.16.1.20250109-win32.win32.x86_64\mat\jdk-17\bin\javaw.exe
3.使用mat分析dump文件
運行MemoryAnalyzer.exe---》file--》open heap dump--》選擇生成的dump文件--》leak suspects report--》finish
打開Overview界面--》Dominator Tree,如下圖:
跳轉到Dominator Tree界面,所有類的占用內存排序顯示出來了,哪些類占用內存一目了然。
展開com.alibaba.druid.pool.DruidDataSource后看到大量的hashMap占用內存,原來是druid監控sql使用的,并不會釋放。