問題描述
在將Spring Boot程序打包生成的war包部署到Tomcat后,啟動Tomcat時總是報錯,但是直接在IDEA中啟動Application或者用"java -jar"方式運行jar包時都能正常運行。報錯信息如下:
To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
(為了防止內存泄漏,已強制注銷JDBC驅動程序。)
開發環境
Spring Boot + MySql + Spring Security + Druid + Mybatis-Plus
- Spring Boot版本:2.1.8.RELEASE
- mysql-connector-java版本:8.0.18
- Druid版本:1.1.20
- Tomcat版本:8.X
解決方法
概述:保證部署環境和開發環境一致,即獨立Tomcat的版本和IDEA中的Tomcat版本保持一致
為了解決這個問題,我花費了兩天時間查找各種資料,但用盡了各種方法都沒能解決問題。就在快要絕望的時候,我想到獨立的Tomcat會報錯,但是IDEA中的Tomcat卻可以正常啟動,是不是因為兩者的版本不同導致的?
於是開始用以下的方法排查問題:
- 在IDEA中啟動Application,查看Tomcat版本:(9.0.24)

- 查看獨立Tomcat版本:(8.5.32)

可以看到兩者的版本號不同,所以我去Tomcat官網下載了版本號為9.0.X的Tomcat,然后將war包部署到webapps中,啟動Tomcat。這次沒有報錯,問題解決!
附:具體解決思路
具體錯誤信息

錯誤大致有以下幾個:
-
The web application [] registered the JDBC driver [com.alibaba.druid.proxy.DruidDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
-
The web application [] registered the JDBC driver [com.mysql.cj.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
-
The web application [] appears to have started a thread named [mysql-cj-abandoned-connection-cleanup] but has failed to stop it. This is very likely to create a memory leak.
所以從字面意義上可以看出,報錯原因大致為:
Web應用程序注冊了JBDC驅動程序[com.mysql.cj.jdbc.Driver],但在Web應用程序停止時未能注銷它。為了防止內存泄漏,已強制注銷JDBC驅動程序。
網上給出的錯誤原因是:
從6.0.24版本開始,Tomcat附帶了內存泄漏檢測功能,當webapp中存在與JDBC 4.0兼容的驅動程序時,該漏洞又會導致這種警告消息,該驅動程序會在使用API啟動webapp的過程/WEB-INF/lib中自動進行注冊,但是在webapp關閉期間未自動注銷自身。
網上給出的幾種解決方案:(都未能解決我的問題,可能是錯誤原因不同)
- 降級到Tomcat 6.0.23或更早的版本。
- 將JDBC驅動程序移至Tomcat的/lib文件夾,並具有連接池數據源來管理驅動程序。
- 將Tomcat安裝目錄中下的server.xml文件中的
標簽全部注釋掉,並將將reloadable="true"改為 false。
