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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

fgc java,频繁FGC的真凶原来是它

發布時間:2023/12/19 综合教程 41 生活家
生活随笔 收集整理的這篇文章主要介紹了 fgc java,频繁FGC的真凶原来是它 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

頻繁FGC的真兇原來是它

上周排查了一個線上問題,主要現象是CPU占用過高,jvm old區占用過高,同時頻繁fgc,我簡單排查了下就草草收場了,但是過后我對這個問題又進行了復查,發現問題沒有那么簡單,下面跟著我一起分析一下到底是怎么回事?

復查過程

復查原因

事后再看dump文件注意到最大的對象是一個ArrayList,里面幾乎都是ElasticSearchStatusException對象

可是發生這個異常的操作上次已經被我定位到了,數據漏斗只有產品、運營等內部人員使用,通過使用頻率推測,不應該有那么多對象。我猜想是不是代碼中存在死循環,但沒有找到。沒辦法只能在測試環境進行場景復現了。

復原現場

通過上次排查到是es查詢了不存在的索引導致異常,所以就把查詢es的索引寫死一個不存在的,最初嘗試寫個單測,但一直不能復現問題,所以只好部署到測試環境,在本地通過遠程debug 調試程序

遠程debug到斷點時,發現源碼對不上

然后發現有可選擇的源碼,這里是關鍵

從org.apache.commons.lang:2.5jar包切換到springsource.org.apache.commons.lang:2.1.0包后,竟然能夠和測試環境對得上,可是代碼中明明引用的commons.lang:2.5的包,這里說明在項目中類加載的時候,ExceptionUtils這個class文件并不是從commons.lang中加載的,而是從springsource包中加載的 關于類文件加載的問題我們先放到后面,先找代碼的問題

看到這里,眼尖的朋友應該已經發現了bug的所在,那么恭喜你。如果沒發現的朋友,不要著急,跟我一步一步來。我們繼續debug跟進代碼的 getCause方法,可以看到通過遍歷異常名字的數組驗證是否在拋出的異常中存在

這些異常方法中的getRootCause方法,存在ElasticSearchStatusException的父類ElasticsearchException中

我們看下這個方法,主要找最根本的異常原因,有則返回,沒有就返回當前的異常

繼續跟代碼,cause不為null,返回這個異常

bug代碼定位

這個getThrowables方法,里面有個while循環,判斷條件只進行了非空判斷,不為null就添加到list中,注意觀察我截圖的時刻,list的大小 8萬多,其實遠遠不止會看開頭dump文件的大對象,是一個ArrayList,里面有大量的ElasticSearchStatusException對象

其實到這里已經定位到了FGC的真兇,判斷條件沒有排除返回的異常是已經添加到list中的異常,所以會一直循環添加,造成堆內存占用滿了,FGC回收不掉這些對象,因為ArrayList一直持有他們的引用

正確代碼應該如下面這樣,所以開源工具庫也是會有bug的,用的時候多加注意

public static Throwable[] getThrowables(Throwable throwable) {

List list = new ArrayList();

// 這里的判斷條件應該加上 list.contains(throwable) == false

while (throwable != null && list.contains(throwable) == false) {

list.add(throwable);

throwable = ExceptionUtils.getCause(throwable);

}

return (Throwable[]) list.toArray(new Throwable[list.size()]);

}

本來我們就沒想用springsource的方法,只是類加載的時候加載錯了,那看下commons.lang包下的方法是否正確呢?可以看到這個包的方法是正確的,考慮到了這個問題

springsource的commons.lang包在2.2版本已經修復了這個問題 jar包最好引用最新的

class文件加載問題

上面我們留了一個jvm加載class文件的問題,我們知道jvm加載class的時候,如果存在包名和類名完全一樣,先加載一個后,另外的就不會再被加載了。

經查看兩個ExceptionUtils確實包名類名完全一致

其實通過前面的debug和代碼分析,已經能確定項目加載的ExceptionUtils.class文件來自springsource包,但還是想通過一定手段驗證一下。

其實jvm提供類類似的功能參數,修改項目啟動腳本,添加jvm參數 -XX:+TraceClassLoading 然后重啟項目并繼讓異常重現【這里要讓觸發異常重現,是因為是運行時異常】,并查看日志,查看ExceptionUtils.class的加載信息

可以看到確實和我們推測的一樣

其實這里還可以深入研究jvm的類加載機制,類加載器加載順序,雙親委派模型等

如何解決

通過 mvn dependency:tree 查看jar包依賴情況,排除掉不用的jar包

結尾

到這里這個問題的排查應該告一段落了,從排查過程中學到了不少,場景復現,梳理思路,用文章分享出來雖說碼字不易很耗時,但這是對自己的一種總結,里面還是有很多樂趣與收獲的。

后續會繼續分享一些和廣告系統相關的文章,敬請期待!

歡迎關注公眾號 【每天曬白牙】,獲取最新文章,我們一起交流,共同進步!

總結

以上是生活随笔為你收集整理的fgc java,频繁FGC的真凶原来是它的全部內容,希望文章能夠幫你解決所遇到的問題。

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