web-dev-qa-db-fra.com

Le pilote JDBC n'a pas été enregistré de force par Tomcat 7, pourquoi?

J'ai un problème avec Tomcat 7, et voici quelques informations à ce sujet,

1 - J'ai ce message:

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 - Lorsque je recharge l'application, le problème résolu pendant environ 20 heures revient.

3 - J'ai environ 10 applications déployées sur le Tomcat, mais seulement 2 d'entre elles reçoivent cette erreur.

4 - le problème n'existait pas depuis la mendicité avec ces 2 applications mais est apparu depuis environ 2 semaines.

Alors, comment puis-je résoudre ce problème et est-ce lié à mon code?

17
AAH

Lorsque vous arrêtez une application Web dans Tomcat, elle essaie d'arrêter les threads qu'elle a démarrés et ferme un tas de ressources, par exemple les pilotes JDBC. Bien que dans ce cas, il soit capable de les fermer, il est plus sûr de le faire vous-même.

Vous pouvez le faire dans un ServletContextListener. J'ai implémenté le mien comme suit

@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 démarre un thread que Tomcat ne peut pas fermer. Pour les versions actuelles (5.1.23+), ils ont fourni la classe AbandonedConnectionCleanupThread pour fermer le Thread généré, comme vous pouvez le voir ci-dessus.

18

Si vous avez votre pilote JDBC Connector/J dans chaque application Web WEB-INF/lib, vous aurez probablement des problèmes similaires avec toutes vos applications Web - pas seulement celle-ci.

Si vous utilisez le pool de connexions JDBC de Tomcat, vous devez placer le pilote Connector/J dans le lib/ répertoire et supprimez-le de toutes vos applications Web. Si vous gérez votre propre pool de connexions à partir de votre propre application, vous devrez vous arranger pour que le pilote JDBC se désenregistre lui-même avec le global DriverManager. Mieux encore, utilisez le pilote non enregistreur de Connector/J au lieu du pilote enregistreur et vous n'aurez plus à vous soucier de ces types de fuites dont Tomcat est vous protégeant en fait de.

5