Tomcat报WebappClassLoaderBase非法访问 应用已停止解决方案
错误产生原因
这个报错的本质是Web应用实例销毁后,未被正常回收的残留线程仍尝试通过已失效的Web应用类加载器加载资源:
- 从堆栈可以定位到肇事线程是JDK内置的
Timer-0定时线程:JDK的java.util.prefs.FileSystemPreferences在首次被调用时,会启动一个固定间隔为5秒的守护定时任务,负责把JVM内存中的偏好设置缓存刷写到磁盘。 - 当你卸载应用、重启Tomcat上下文时,这个定时线程属于JVM全局线程,不会随Web应用上下文的销毁自动终止,会一直留存在JVM进程中运行。
- 应用停止后,负责加载该应用所有类和资源的
WebappClassLoader已经被标记为销毁状态,残留的定时任务执行到XML解析逻辑时,需要加载META-INF/services/javax.xml.parsers.DocumentBuilderFactory的SPI配置,只能通过已失效的类加载器查找资源,就会抛出该异常。
你提到关闭Tomcat重新部署后错误仍每5秒打印,是因为旧的Tomcat进程根本没有真正退出,后台残留的JVM进程还带着这个泄漏的线程持续运行,你启动的新Tomcat实例和报错的旧进程是两个独立进程。
可行解决方案
按优先级从高到低可以选择以下方案处理:
- 临时快速修复:先彻底清理残留进程。Linux环境执行
ps -ef | grep tomcat找到所有关联旧Tomcat的Java进程,用kill -9 进程ID强制终止;Windows环境通过任务管理器找到残留的java.exe进程手动结束。确认无残留进程后再重新启动Tomcat部署应用,报错会直接消失。 - 根治线程泄漏:如果业务代码或者第三方依赖主动调用了JDK的Preferences相关API,要在应用销毁的生命周期回调里(比如Spring中使用
@PreDestroy注解、实现DisposableBean接口)主动终止Preferences的同步任务,避免应用停止后线程残留。 - 开启Tomcat自带泄漏防护:使用外部Tomcat部署war包的场景,可以在Tomcat的
conf/context.xml中配置JRE内存泄漏防护监听器,让Tomcat在应用卸载时主动扫描并终止这类JDK遗留的泄漏线程:
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
- 临时屏蔽日志:如果短时间无法定位泄漏根源,可以修改Tomcat的
conf/logging.properties配置,将org.apache.catalina.loader.WebappClassLoaderBase的日志级别调整为SEVERE,屏蔽这类INFO级别的无效报错。注意这个方案仅能隐藏日志,无法解决内存泄漏问题,不推荐长期使用。
内容的提问来源于stack exchange,提问作者PseudoDev
相关产品推荐
相关产品推荐

