Драйвер JDBC был принудительно незарегистрирован Tomcat 7, почему?
У меня есть проблема в tomcat 7, и вот некоторые сведения об этом,
1 - У меня есть это сообщение:
INFO: Reloading Context with name [/WebApp] has started
Oct 04, 2013 12:20:50 PM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [/WebApp] registered the JDBC driver [com.mysql.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.
Oct 04, 2013 12:20:50 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/WebApp] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak.
Oct 04, 2013 12:20:51 PM org.apache.catalina.core.StandardContext reload
INFO: Reloading Context with name [/WebApp] is completed
2 - Когда я перезагружаю приложение, проблема решена в течение примерно 20 часов, а затем возвращается снова.
3 - У меня около 10 приложений, развернутых на tomcat, но только 2 из них получают эту ошибку.
4 - проблема не существовала от попрошайничества с этими 2 приложениями, но появилась примерно через 2 недели.
Итак, как я могу решить эту проблему и связан ли это с моим кодом?
Ответы
Ответ 1
Когда вы останавливаете веб-приложение в Tomcat, оно пытается завершить запущенные потоки и закрывает кучу ресурсов, например драйверы JDBC. Хотя в этом случае он способен их закрыть, безопаснее делать это самостоятельно.
Вы можете сделать это в ServletContextListener
. Я выполнил мою работу следующим образом
@WebListener // register it as you wish
public class ContainerContextClosedHandler implements ServletContextListener {
private static final Logger logger = LoggerFactory.getLogger(ContainerContextClosedHandler.class);
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
// nothing to do
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
Enumeration<Driver> drivers = DriverManager.getDrivers();
Driver driver = null;
// clear drivers
while(drivers.hasMoreElements()) {
try {
driver = drivers.nextElement();
DriverManager.deregisterDriver(driver);
} catch (SQLException ex) {
// deregistration failed, might want to do something, log at the very least
}
}
// MySQL driver leaves around a thread. This static method cleans it up.
try {
AbandonedConnectionCleanupThread.shutdown();
} catch (InterruptedException e) {
// again failure, not much you can do
}
}
}
MySQL запускает Thread, который Tomcat не может закрыть. Для текущих версий (5.1.23+) они предоставили класс AbandonedConnectionCleanupThread
для закрытия порожденного Thread
, как вы можете видеть выше.
Ответ 2
Если у вас есть драйвер Connector/J JDBC в каждом каталоге webapp WEB-INF/lib
, тогда у вас, скорее всего, будут проблемы со всеми вашими веб-приложениями, а не только с этим.
Если вы используете пул соединений Tomcat JDBC, вам следует поместить драйвер Connector/J в каталог Tomcat lib/
и удалить его со всех ваших веб-приложений. Если вы поддерживаете свой собственный пул подключений из своего собственного приложения, вам необходимо будет настроить, чтобы драйвер JDBC был деинфицирован с глобальным DriverManager
. Еще лучше, используйте драйвер, не регистрирующий Connector/J вместо драйвера регистрации, и вам не придется беспокоиться об этих утечках, которые Tomcat фактически защищает вас.