发布于 

一次java.lang.OutOfMemoryError:Metaspace处理

其实这个问题非常明显就是Metaspace内存不够导致溢出,调整jvm的-XX:MetaspaceSize=56m -XX:MaxMetaspaceSize=128m元空间大小参数就能解决。但是根据甲方要求,必须要给出明确的解释,排除是否是内存泄露导致的OutOfMemoryError: Metaspac报错。没有办法,甲方爸爸的要求。那就找点证据说明就是内存给小了的问题。

由于之前的容器已经清除,只能在配置一样的环境中分析。
首先查看当前jvm Metaspace分配的空间大小。我是通过arthas的jvm命令进行查看的。
首先拉去arthas的jar包。

1
curl -O https://arthas.aliyun.com/arthas-boot.jar

然后将jar复制到你要查看项目的docker容器中去

1
docker cp ./arthas-boot.jar  {容器名称或id}:/home/

进入容器

1
docker exec -it {容器名称或id} sh

启动arthas-boot.jar

1
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下来到本地分析查看。

1
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大部分都发生在新生代。说明配置有效。
这是我第一次实战调优,要是哪里有问题请指出,互相学习一下。


本站由 @binvv 使用 Stellar 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。