其實這個問題非常明顯就是Metaspace內存不夠導致溢出,調整jvm的-XX:MetaspaceSize=56m -XX:MaxMetaspaceSize=128m元空間大小參數就能解決。但是根據甲方要求,必須要給出明確的解釋,排除是否是內存泄露導致的OutOfMemoryError: Metaspac報錯。沒有辦法,甲方爸爸的要求。那就找點證據說明就是內存給小了的問題。
由於之前的容器已經清除,只能在配置一樣的環境中分析。 首先查看當前jvm Metaspace分配的空間大小。我是通過arthas的jvm命令進行查看的。 首先拉去arthas的jar包。
curl -O https://arthas.aliyun.com/arthas-boot.jar
然後將jar複製到你要查看項目的docker容器中去
docker cp ./arthas-boot.jar {容器名稱或id}:/home/
進入容器
docker exec -it {容器名稱或id} sh
啓動arthas-boot.jar
java -jar arthas-boot.jar
看到以上證明啓動成功
輸入jvm查看jvm信息
和啓動配置是一致的。(退出arthas最好使用stop,不然在其他docker中啓動會監控的依然是這個項目。) arthas文檔地址:https://arthas.aliyun.com/doc/install-detail.html 這個工具功能還有很多比如監控代碼執行時間等等。
接下來使用jstat查看項目的gc狀況 在容器中輸入jps,然後就可以使用jstat命令查看。輸入jstat -gcutil pid查看gc概要信息
列名稱 | 描述 |
---|---|
S0 | S0(Survivor 0)空間使用百分比(相對於當前容量) |
S1 | S1(Survivor 1)空間使用百分比(相對於當前容量) |
E | Eden空間使用百分比(相對於當前容量) |
O | 老年代空間使用百分比(相對於當前容量) |
M | 元空間(Metaspace)使用百分比(相對於當前容量) |
CCS | CCS空間使用百分比 |
YGC | 新生代GC(Minor GC/Young GC)發生的次數 |
YGCT | YGC所消耗的時間, 單位s |
FGC | Full GC發生的次數 |
FGCT | Full GC消耗的時間, 單位s |
GCT | 所有GC消耗的總時間, 單位s |
通過上圖分析新生代發生了大量的gc,導致老年代數據快速積壓,然後發生Full GC。 接下來將jvm的加載類使用jmap dump下來到本地分析查看。
jmap -dump:live,format=b,file=dump.hprof 6
可以看到本地生成了個dump.hprof 文件
將它拉取到本地,使用JProfiler打開 JProfiler官網:https://www.ej-technologies.com/products/jprofiler/overview.html
這些類點進去看看是否有大量創建的異常類
發現沒有異常創建的類,分析就是單純的空間給小了。加大元空間容量分配-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m 再運行2天看看gc狀況
發現新生代gc2w多次,Full GC次數爲0,gc大部分都發生在新生代。說明配置有效。 這是我第一次實戰調優,要是哪裏有問題請指出,互相學習一下。