返回
Hot Deployment Caused OOM?
后端
2023-10-19 10:46:37
热部署引发OOM引发的血案
现象
背景
项目采用Spring Boot,使用热部署插件来实现代码的热加载。
现象
- 在热部署之后,测试环境服务器发生OOM。
- 查看日志发现,OOM时堆内存占用并不高,但元空间(Metaspace)占用却非常高。
问题排查
- 查看元空间占用情况
jmap -histo:live <pid> | grep org.springframework
发现元空间中存在大量org.springframework
的类,这些类是热部署过程中加载的。
- 查看类加载器情况
jmap -dump:format=b,file=dump.bin <pid>
jde -J-Xmx64m -cp tools.jar sun.jvm.hotspot.tools.jcore.ClassDump dump.bin org.springframework.aop.framework.JdkDynamicAopProxy
发现这些类是由自定义的类加载器加载的。
- 查看热部署插件
发现热部署插件使用的是HotSwapAgent
。
问题分析
自定义类加载器
自定义类加载器在加载类时,会将类信息保存到元空间中。当类被卸载时,这些类信息不会被清除,导致元空间内存泄漏。
HotSwapAgent
HotSwapAgent
在热部署时,会将新的类加载到元空间中,但不会卸载旧的类。这会导致元空间内存泄漏。
解决办法
- 禁用自定义类加载器
在项目的pom文件中添加以下配置:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hotswap</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
</exclusion>
</exclusions>
</dependency>
- 使用
JRebel
等热部署工具
JRebel
等热部署工具不会使用自定义类加载器,也不会导致元空间内存泄漏。
总结
本文介绍了如何排查和解决热部署引起的OOM问题。涉及到的JVM基础概念包括元空间和类加载器。排查工具包括jmap
和jde
。