velocity 區間運算符導致生產環境OOM

最近生產環境某些機器頻繁出現FullGC和OOM,用jmap的heap功能查看該Java進程的內存使用情況,如下圖:

184154541.png


問題分析:


再用jmap的histo圖查看當前對象分佈圖,發現有很多Integer(爲啥?不知道啊。。。下面分解)

184246968.png

這裏可以很明顯看到,光Integer就佔用了1G多內存空間。


手工dump一臺的機器,jmap –dump:format=b,file=/home/admin/logs/aaa.bin –F<pid>


這裏將持續很久,而且可能報錯拋異常 UnmappedAddressException,一旦拋出

這種異常,就需要再次重試。另外注意磁盤空間必須保持充足(剩餘空間至少是物理內存1.5倍)。


使用MAT工具,分析dump結果。


觀察出問題的線程,如下圖

184506911.png

還有其heap佔用情況:

184538753.png


可以觀察到,該線程持有一個3G空間大小的Integer數組,剛好印證了之前的histo圖。

那這麼大的一個int數組從哪來就很值得懷疑。查看ASTIntegerRange類的源碼的140行,如下圖:


184607241.png


至此,大概可以確定,問題應該就出在這。

關鍵在於,這個類是Velocity自己的類,我們對此一無所聞,它在哪裏被調用,被誰調用,也無法知道。

查看Apache官方文檔,找到蛛絲馬跡,該類是用來處理[n..m]這種運算符的。


搜了一下整個代碼裏面,只有一個地方用到了該語法:

184705565.png


這裏的endIndex,是後臺根據總頁數直接計算出來的,***者沒法僞造。

但是startIndex則是根據用戶傳入的當前頁數來決定的。

而且最關鍵的一點,該語法既可以是單調增,也可以是單調減(比如[1 .. 100]或者[100 .. 1])


因而,一旦用戶傳入一個很大的當前頁數值,velocity會在內部構建一個大小爲|n-m|的ArrayList(它內部實際上就是數組)

從而導致OOM。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章