現象
正式環境中沒間隔幾個星期就會發生一次內存溢出問題。tomcat版本:8.0.43
SEVERE:
java.lang.OutOfMemoryError: Java heap space
Jul 26, 2019 5:25:39 PM org.apache.tomcat.util.net.NioEndpoint checkParachute
SEVERE: SEVERE:Memory usage is low, parachute is non existent, your system may start failing.
Jul 26, 2019 5:25:39 PM org.apache.tomcat.util.net.NioEndpoint checkParachute
SEVERE: SEVERE:Memory usage is low, parachute is non existent, your system may start failing.
Jul 26, 2019 5:25:45 PM org.apache.tomcat.util.net.NioEndpoint$Acceptor run
SEVERE:
java.lang.OutOfMemoryError: Java heap space
Jul 26, 2019 5:25:57 PM org.apache.tomcat.util.net.NioEndpoint$Acceptor run
SEVERE:
java.lang.OutOfMemoryError: Java heap space
Jul 26, 2019 5:26:02 PM org.apache.tomcat.util.net.NioEndpoint checkParachute
SEVERE: SEVERE:Memory usage is low, parachute is non existent, your system may start failing.
Jul 26, 2019 5:26:08 PM org.apache.tomcat.util.net.NioEndpoint$Acceptor run
SEVERE:
java.lang.OutOfMemoryError: Java heap space
問題定位
查看應用進程號
[user@VM_0_6_centos logs]$ jps
32361 war
21450 Jps
29051 Bootstrap
內存快照導出
jmap -dump:format=b,file=./dump/jmap.hprof 29051
使用mat對快照分析
分析結果
10,735 instances of "org.apache.coyote.RequestInfo", loaded by "java.net.URLClassLoader @ 0xc1044bf8" occupy 1,160,848,488 (91.15%) bytes. These instances are referenced from one instance of "java.lang.Object[]", loaded by "<system class loader>"
Keywords
java.lang.Object[]
org.apache.coyote.RequestInfo
java.net.URLClassLoader @ 0xc1044bf8
Details »
系統中存在大量的RequestInfo對象,點擊對象發現請求地址都是tomcat下webapp下面的靜態資源文件,而不是web應用的url。
之前為了定位問題開啟了tomcat的控制台用來監控狀態。
可以看到old gen異常,下面的請求數有1萬多個。正好對應上面的requestinfo對象數量。
異常復現:
把整個tomcat復制一份,修改端口后啟動,用ab壓測了一下:
壓測前:
只有一個請求。
壓測后:請求數增加為100。
#請求300次,100線程。
ab -n300 -c100 http://ip:port/uploadCwis/images/2018/08/13/2db8d60a-1c83-460c-ab33-c8b1f8abc13f.jpg
第二次壓測:
使用相同參數壓測:
請求數變為600。
第三次壓測:
使用相同參數壓測:
請求數變為900。
。。。
每多測一次,請求次數增加,完全不釋放或復用。
從官網下載相同版本的tomcat,jvm參數改為一致后進行相同的測試。
發現多測測試后最多請求數不到200。開始懷疑這個tomcat有問題。
使用bcompare對tomcat的jar文件進行對比。
發現lib\tomcat-coyote.jar的AbstractProtocol類有不同的地方。
使用jad反編譯后對這個類進行進一步比較
左邊是正式環境。右邊的是官網版本。
發現兩個版本對於AbstractEndpoint.Handler.SocketState.SENDFILE
處理有所不同。
正式環境的是使用release(wrapper, processor, true, false);
,
官網版本使用的是 this.connections.put(socket, processor);
然而對比github上tomcat其他的版本。又有所不同。(這些變更的意義是什么???)
直接使用官網下載的jar替換公司環境,壓測后正常。