Maven - StackOverflowError


問題與分析

今天發現服務器上的Jenkins在集成項目時報錯,報錯原因如下:

error compiling: java.lang.StackOverflowError -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.

還是頭回遇到這種錯誤,由於Jenkins每天晚上都會自動集成當天提交的代碼。之前一直編譯正常,而今天編譯報錯,正好昨天我提交了代碼上去。

很顯然,這是由於我提交的代碼造成的。一開始以為是項目代碼有問題,比如無限遞歸之類的導致的堆棧溢出。但是在本地發現可以正常運行該Maven項目,無論是編譯還是打包都一切正常。難道是Jenkins抽風了?於是重啟了Jenkins任務去重新編譯一次項目,結果再次掛了,報了同樣的錯誤。

百度之后發現挺多人都遇到這種問題,原因也基本一樣,都是因為jvm內存不足導致的堆棧溢出。仔細想想,確實很有可能,因為我在本地是通過eclipse來運行項目的,我在本地配置了足夠的jvm參數;而服務器上則可能由於Jenkins同時運行多個任務,又或者配置的內存不夠,所以就編譯報錯了。

再一次審視我昨晚提交的代碼,發現在一個測試類里,有個方法調用了非常多的api,這個方法的方法體里大概調用了四百多個api。之所以會方法體這么長,是因為該方法用來測試某個pojo類里的字段是否和數據庫里的字段能否匹配上。因為pojo里的字段有四百多個,所以就導致該方法體如此之冗長了。

也就是說,很有可能是該方法導致Jenkins在運行該測試類的該方法時調用api過多導致堆棧溢出了。於是重新修改了代碼,將該方法里調用的api分別放到了另外兩個方法里,大概一個方法里調用兩百個api,然后測試類原來的方法則調用這兩個新添加的方法。

之后提交代碼,重新讓Jenkins集成代碼,發現不再報錯。

解決方法

和老大討論之后,決定采用修改代碼的方式去fix這個問題。可能是處於服務器內存緊張的考慮,又或者是別的什么因素,不采用網友博文里說的加大jvm參數的方案。

這里還是總結下這兩個方案:

方案一

在項目的啟動腳本里加大jvm參數,如下:

set MAVEN_OPTS=-Xss4096k

也可以不用設置得那么大,比如設置成下面這樣:

set MAVEN_OPTS=-Xss2m

方案二

修改代碼內某個調用了過多api的方法,可以將其一分為二,拆分成多個子方法,各自調用一部分的api,最后由原來的方法來call這幾個拆分開來的子方法。總之,應當避免在一個方法內調用過多api。

其他

這里順便貼一下公司項目設置的參數:

echo off
setlocal
set MAVEN_DEBUG_OPTS=-Duser.timezone=GMT+8 -Xdebug -Xmx4096M -XX:PermSize=128M -XX:MaxPermSize=512M -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8088,server=y,suspend=n
mvn spring-boot:run
endlocal

參考鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM