返回

Hot Deployment Caused OOM?

后端

热部署引发OOM引发的血案

现象

背景

项目采用Spring Boot,使用热部署插件来实现代码的热加载。

现象

  1. 在热部署之后,测试环境服务器发生OOM。
  2. 查看日志发现,OOM时堆内存占用并不高,但元空间(Metaspace)占用却非常高。

问题排查

  1. 查看元空间占用情况
jmap -histo:live <pid> | grep org.springframework

发现元空间中存在大量org.springframework的类,这些类是热部署过程中加载的。

  1. 查看类加载器情况
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

发现这些类是由自定义的类加载器加载的。

  1. 查看热部署插件

发现热部署插件使用的是HotSwapAgent

问题分析

自定义类加载器

自定义类加载器在加载类时,会将类信息保存到元空间中。当类被卸载时,这些类信息不会被清除,导致元空间内存泄漏。

HotSwapAgent

HotSwapAgent在热部署时,会将新的类加载到元空间中,但不会卸载旧的类。这会导致元空间内存泄漏。

解决办法

  1. 禁用自定义类加载器

在项目的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>
  1. 使用JRebel等热部署工具

JRebel等热部署工具不会使用自定义类加载器,也不会导致元空间内存泄漏。

总结

本文介绍了如何排查和解决热部署引起的OOM问题。涉及到的JVM基础概念包括元空间和类加载器。排查工具包括jmapjde