To prevent a memory leak, the JDBC Driver has been forcibly unregistered

后端 未结 14 1474
执念已碎
执念已碎 2020-11-22 02:15

I am getting this message when I run my web application. It runs fine but I get this message during shutdown.

SEVERE: A web application registered the

相关标签:
14条回答
  • 2020-11-22 03:09

    In your servlet context listener contextDestroyed() method, manually deregister the drivers:

    // This manually deregisters JDBC driver, which prevents Tomcat 7 from complaining about memory leaks wrto this class
    Enumeration<Driver> 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);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 03:09

    I found the same issue with Tomcat version 6.026.

    I used the Mysql JDBC.jar in WebAPP Library as well as in TOMCAT Lib.

    To fix the above by removing the Jar from the TOMCAT lib folder.

    So what I understand is that TOMCAT is handling the JDBC memory leak properly. But if the MYSQL Jdbc jar is duplicated in WebApp and Tomcat Lib, Tomcat will only be able to handle the jar present in the Tomcat Lib folder.

    0 讨论(0)
  • 2020-11-22 03:15

    This error happened to me in a Grails Application with the JTDS Driver 1.3.0 (SQL Server). The problem was an incorrect login in SQL Server. After solve this issue (in SQL Server) my app was correctly deployed in Tomcat. Tip: I saw the error in stacktrace.log

    0 讨论(0)
  • 2020-11-22 03:17

    I have faced this problem when I was deploying my Grails application on AWS. This is matter of JDBC default driver org.h2 driver . As you can see this in the Datasource.groovy inside your configuration folder . As you can see below :

    dataSource {
        pooled = true
        jmxExport = true
        driverClassName = "org.h2.Driver"   // make this one comment
        username = "sa"
        password = ""
    }
    

    Comment those lines wherever there is mentioned org.h2.Driver in the datasource.groovy file , if you are not using that database . Otherwise you have to download that database jar file .

    Thanks .

    0 讨论(0)
  • 2020-11-22 03:18

    To prevent this memory leak, simply deregister the driver on context shutdown.

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.mywebsite</groupId>
        <artifactId>emusicstore</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.7.0</version>
                    <configuration>
                        <source>1.9</source>
                        <target>1.9</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
        <dependencies>
            <!-- ... -->
    
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-core</artifactId>
                <version>4.0.1.Final</version>
            </dependency>
    
            <dependency>
                <groupId>org.hibernate.javax.persistence</groupId>
                <artifactId>hibernate-jpa-2.0-api</artifactId>
                <version>1.0.1.Final</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.11</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>2.5</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    
    </project>
    

    MyWebAppContextListener.java

    package com.emusicstore.utils;
    
    import com.mysql.cj.jdbc.AbandonedConnectionCleanupThread;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import java.sql.Driver;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.Enumeration;
    
    public class MyWebAppContextListener implements ServletContextListener {
    
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            System.out.println("************** Starting up! **************");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
            System.out.println("************** Shutting down! **************");
            System.out.println("Destroying Context...");
            System.out.println("Calling MySQL AbandonedConnectionCleanupThread checkedShutdown");
            AbandonedConnectionCleanupThread.checkedShutdown();
    
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
    
            Enumeration<Driver> drivers = DriverManager.getDrivers();
            while (drivers.hasMoreElements()) {
                Driver driver = drivers.nextElement();
    
                if (driver.getClass().getClassLoader() == cl) {
                    try {
                        System.out.println("Deregistering JDBC driver {}");
                        DriverManager.deregisterDriver(driver);
    
                    } catch (SQLException ex) {
                        System.out.println("Error deregistering JDBC driver {}");
                        ex.printStackTrace();
                    }
                } else {
                    System.out.println("Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader");
                }
            }
        }
    
    }
    

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                                 http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <listener>
            <listener-class>com.emusicstore.utils.MyWebAppContextListener</listener-class>
        </listener>
    
    <!-- ... -->
    
    </web-app>
    

    Source that inspired me for this bug fix.

    0 讨论(0)
  • 2020-11-22 03:19

    I see this issue come up a lot. Yes, Tomcat 7 does automatically deregister it, but it that REALLY taking control of your code and a good coding practice? Surely YOU want to know that you have all the correct code in place to close all your objects, shut down database connection pool threads, and get rid of all warnings. I certainly do.

    This is how I do it.

    Step 1: Register a Listener

    web.xml

    <listener>
        <listener-class>com.mysite.MySpecialListener</listener-class>
    </listener>
    

    Step 2: Implement the Listener

    com.mysite.MySpecialListener.java

    public class MySpecialListener implements ServletContextListener {
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            // On Application Startup, please…
    
            // Usually I'll make a singleton in here, set up my pool, etc.
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            // On Application Shutdown, please…
    
            // 1. Go fetch that DataSource
            Context initContext = new InitialContext();
            Context envContext  = (Context)initContext.lookup("java:/comp/env");
            DataSource datasource = (DataSource)envContext.lookup("jdbc/database");
    
            // 2. Deregister Driver
            try {
                java.sql.Driver mySqlDriver = DriverManager.getDriver("jdbc:mysql://localhost:3306/");
                DriverManager.deregisterDriver(mySqlDriver);
            } catch (SQLException ex) {
                logger.info("Could not deregister driver:".concat(ex.getMessage()));
            } 
    
            // 3. For added safety, remove the reference to dataSource for GC to enjoy.
            dataSource = null;
        }
    
    }
    

    Please feel free to comment and/or add...

    0 讨论(0)
提交回复
热议问题