Saltar al contenido

Para evitar una fuga de memoria, el controlador JDBC se ha desregistrado a la fuerza.

Luego de de nuestra larga búsqueda de información hemos podido solucionar esta dificultad que presentan ciertos de nuestros usuarios. Te dejamos la respuesta y nuestro deseo es servirte de mucha apoyo.

Solución:

Desde la versión 6.0.24, Tomcat incluye una función de detección de fugas de memoria, que a su vez puede generar este tipo de mensajes de advertencia cuando hay un controlador compatible con JDBC 4.0 en la aplicación web. /WEB-INF/lib que se registra automáticamente durante el inicio de la aplicación web usando el ServiceLoader API, pero que no se canceló automáticamente durante el cierre de la aplicación web. Este mensaje es puramente informal, Tomcat ya ha tomado la acción de prevención de pérdida de memoria correspondiente.

¿Qué puedes hacer?

  1. Ignora esas advertencias. Tomcat está haciendo bien su trabajo. El error real está en el código de otra persona (el controlador JDBC en cuestión), no en el suyo. Alégrese de que Tomcat hizo su trabajo correctamente y espere hasta que el proveedor del controlador JDBC lo arregle para que pueda actualizar el controlador. Por otro lado, se supone que no debe colocar un controlador JDBC en la aplicación web /WEB-INF/libpero solo en el servidor /lib. Si todavía lo mantienes en webapp’s /WEB-INF/libentonces debe registrarlo y cancelarlo manualmente usando un ServletContextListener.

  2. Cambie a Tomcat 6.0.23 o anterior para que no le molesten esas advertencias. Pero en silencio seguirá perdiendo memoria. No estoy seguro de si es bueno saberlo después de todo. Ese tipo de fugas de memoria son una de las principales causas detrás OutOfMemoryError problemas durante las implementaciones activas de Tomcat.

  3. Mueva el controlador JDBC a Tomcat /lib carpeta y tener una fuente de datos agrupada de conexión para administrar el controlador. Tenga en cuenta que el DBCP integrado de Tomcat no anula el registro de los controladores correctamente al cerrar. Consulte también el error DBCP-322, que está cerrado como WONTFIX. Preferiría reemplazar DBCP por otro grupo de conexiones que está haciendo su trabajo mejor que DBCP. Por ejemplo, HikariCP o quizás Tomcat JDBC Pool.

En su método de escucha de contexto de servlet contextDestroyed(), anule manualmente el registro de los controladores:

// This manually deregisters JDBC driver, which prevents Tomcat 7 from complaining about memory leaks wrto this class
Enumeration drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) 
    Driver driver = drivers.nextElement();
    try 
        DriverManager.deregisterDriver(driver);
        LOG.log(Level.INFO, String.format("deregistering jdbc driver: %s", driver));
     catch (SQLException e) 
        LOG.log(Level.SEVERE, String.format("Error deregistering driver %s", driver), e);
    

Aunque Tomcat cancela el registro del controlador JDBC por la fuerza, es una buena práctica limpiar todos los recursos creados por su aplicación web en la destrucción de contexto en caso de que se mueva a otro contenedor de servlet que no realiza las comprobaciones de prevención de fugas de memoria que hace Tomcat.

Sin embargo, la metodología de cancelación general del registro de conductores es peligrosa. Algunos conductores devueltos por el DriverManager.getDrivers() El método puede haber sido cargado por el ClassLoader principal (es decir, el cargador de clases del contenedor del servlet) y no por el ClassLoader del contexto de la aplicación web (por ejemplo, pueden estar en la carpeta lib del contenedor, no en la aplicación web y, por lo tanto, compartidas en todo el contenedor). Anular el registro de estos afectará a cualquier otra aplicación web que pueda estar usándolos (o incluso al propio contenedor).

Por lo tanto, se debe verificar que el ClassLoader para cada controlador sea el ClassLoader de la aplicación web antes de cancelar el registro. Entonces, en el método contextDestroyed() de ContextListener:

public final void contextDestroyed(ServletContextEvent sce) 
    // ... First close any background tasks which may be using the DB ...
    // ... Then close any DB connection pools ...

    // Now deregister JDBC drivers in this context's ClassLoader:
    // Get the webapp's ClassLoader
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    // Loop through all drivers
    Enumeration drivers = DriverManager.getDrivers();
    while (drivers.hasMoreElements()) 
        Driver driver = drivers.nextElement();
        if (driver.getClass().getClassLoader() == cl) 
            // This driver was registered by the webapp's ClassLoader, so deregister it:
            try 
                log.info("Deregistering JDBC driver ", driver);
                DriverManager.deregisterDriver(driver);
             catch (SQLException ex) 
                log.error("Error deregistering JDBC driver ", driver, ex);
            
         else 
            // driver was not registered by the webapp's ClassLoader and may be in use elsewhere
            log.trace("Not deregistering JDBC driver  as it does not belong to this webapp's ClassLoader", driver);
        
    

Aquí tienes las reseñas y puntuaciones

Si te sientes a gusto, tienes la habilidad dejar una división acerca de qué le añadirías a esta reseña.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *