升级Tomcat9后重部署Spring Boot应用触发ehcache致JVM崩溃
问题诊断与解决方案
核心原因分析
- Tomcat 9.0.x 与 Ehcache 3.9.0 的类加载器兼容性冲突:Tomcat 9 调整了类加载机制,尤其是Web应用重部署时的类卸载逻辑,而Ehcache 3.9.0存在未正确释放的全局资源(如缓存管理器实例、内存映射文件),导致类加载器无法被回收,触发JVM层面的halt错误。
- 多版本应用缓存资源抢占:同一Tomcat实例运行两个同应用不同版本时,若Ehcache使用全局静态实例或未隔离的配置,重部署时新旧版本的缓存组件会出现资源冲突,引发底层VM错误。
- Ehcache 3.9.0 已知Bug:该版本存在类加载器相关的资源泄漏问题,在Web容器重部署场景下易触发JVM halt异常。
分步解决方案
升级Ehcache版本
直接升级至Ehcache 3.10.0及以上版本,官方后续版本修复了多个类加载器泄漏和Web容器部署相关Bug,包含针对Tomcat 9的兼容性优化。配置Ehcache类加载器隔离
在Spring Boot应用的Ehcache配置中,明确指定使用当前Web应用的类加载器,避免依赖全局类加载器:CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() .classLoader(this.getClass().getClassLoader()) .build(true);或在
ehcache.xml中添加类加载器配置:<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd"> <classLoader>${java.class.path}</classLoader> <!-- 其他缓存配置 --> </config>优化Tomcat资源回收配置
在Tomcat的conf/context.xml中添加以下配置,增强类加载器回收能力:<Context> <Loader useSystemClassLoaderAsParent="false" clearReferencesStopTimerThreads="true"/> <Resources cachingAllowed="true" cacheMaxSize="100000"/> </Context>该配置会强制Tomcat在应用卸载时清理线程和类加载器引用,降低资源泄漏风险。
隔离多版本应用缓存实例
确保两个不同版本的应用使用独立的CacheManager实例,避免共享全局缓存资源:- 在Spring Boot中通过
@Bean自定义CacheManager,为每个应用指定唯一的缓存名称前缀或独立配置:@Bean public CacheManager ehCacheManager() { return CacheManagerBuilder.newCacheManagerBuilder() .withCache("getAccountSettingByState", CacheConfigurationBuilder.newCacheConfigurationBuilder( String.class, AccountSetting.class, ResourcePoolsBuilder.heap(100))) .build(true); }
- 在Spring Boot中通过
排查JVM崩溃日志
收集JVM崩溃生成的hs_err_pid.log文件,查看错误栈和内存地址信息,确认是否为Ehcache内存映射文件(MappedByteBuffer)未释放导致的问题。如果是,可临时禁用磁盘存储排查:<cache alias="getAccountSettingByState"> <key-type>java.lang.String</key-type> <value-type>com.example.AccountSetting</value-type> <resources> <heap unit="entries">100</heap> <!-- 临时禁用磁盘存储 --> <!-- <disk unit="MB">10</disk> --> </resources> </cache>
已知问题参考
- Ehcache官方在3.9.0版本后修复了
CacheManager未正确关闭导致的类加载器泄漏问题(Issue #2978),该问题在Web容器频繁重部署场景下会触发JVM资源耗尽错误。 - Tomcat 9.0.31存在Web应用类卸载相关的小Bug,升级至Tomcat 9.0.40及以上版本可获得更稳定的类加载器回收逻辑。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

