351

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 JBDC driver [oracle.jdbc.driver.OracleDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

Any help appreciated.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
mona
  • 6,079
  • 12
  • 41
  • 46
  • 4
    Could be duplicate of http://stackoverflow.com/questions/2604630/tomcat-fails-to-start-because-of-jdbc-driver-loading – skaffman Jul 23 '10 at 16:46

14 Answers14

320

Since version 6.0.24, Tomcat ships with a memory leak detection feature, which in turn can lead to this kind of warning messages when there's a JDBC 4.0 compatible driver in the webapp's /WEB-INF/lib which auto-registers itself during webapp's startup using the ServiceLoader API, but which did not auto-deregister itself during webapp's shutdown. This message is purely informal, Tomcat has already taken the memory leak prevention action accordingly.

What can you do?

  1. Ignore those warnings. Tomcat is doing its job right. The actual bug is in someone else's code (the JDBC driver in question), not in yours. Be happy that Tomcat did its job properly and wait until the JDBC driver vendor get it fixed so that you can upgrade the driver. On the other hand, you aren't supposed to drop a JDBC driver in webapp's /WEB-INF/lib, but only in server's /lib. If you still keep it in webapp's /WEB-INF/lib, then you should manually register and deregister it using a ServletContextListener.

  2. Downgrade to Tomcat 6.0.23 or older so that you will not be bothered with those warnings. But it will silently keep leaking memory. Not sure if that's good to know after all. Those kind of memory leaks are one of the major causes behind OutOfMemoryError issues during Tomcat hotdeployments.

  3. Move the JDBC driver to Tomcat's /lib folder and have a connection pooled datasource to manage the driver. Note that Tomcat's builtin DBCP does not deregister drivers properly on close. See also bug DBCP-322 which is closed as WONTFIX. You would rather like to replace DBCP by another connection pool which is doing its job better then DBCP. For example HikariCP or perhaps Tomcat JDBC Pool.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 27
    This is good advice. It's not warning of a memory leak, it's a warning that Tomcat took some forcible action to prevent a leak – matt b Jul 23 '10 at 17:43
  • @BalusC, we are not using Tomcat's connection pool, do you think the message should still show up?? – mona Sep 03 '10 at 15:48
  • can we keep it this way or do you suggest to use the fix shown in DBCP-322 that you provided in the answer? I was wondering if we could just ignore those warnings! Thanks for your quick responses... – mona Sep 03 '10 at 15:57
  • I have the same issue as in mona's comment. We're using C3P0 in Spring, but still get the issue. And I'm even running Tomcat 6.0.23, which is below 6.0.24. – Mathias Conradt Mar 08 '11 at 07:31
  • 54
    If option (1) is the way to go, why does Tomcat log these as SEVERE, though? SEVERE to me means "page the admin", not "ignore". – Peter Becker Oct 17 '11 at 23:16
  • 7
    Why not do it yourself - rather than expect Tomcat to do it. In my opinion, it's not Tomcat's job to clean up our messy code. See my answer below. – sparkyspider Oct 19 '11 at 11:24
  • 1
    Just pointing out that this error can cause your session state to be invalid after reloading. I was having that problem until I used the solution mentioned by ae6rt to deregister the drivers. – sproketboy Jun 27 '13 at 22:50
  • 2
    @sproketboy: Huh? Was you assigning JDBC artifacts as fields of a class which is in turn stored in the HTTP session? – BalusC Jun 27 '13 at 23:44
  • 2
    I guess it's usually reason 3 (having the library in the wAR as opposed to `lib`). – lapo Nov 25 '14 at 09:42
  • 1
    @BalusC Does this warning comes when we restart the tomcat server???Does this warning cause tomcat to stop.My tomcat server is being stopped within 2 or 3 days after i started it.I deployed my webapp and it's been up and running for some time and one day it suddenly crashed.Is this could be the reason.I found below lines as something unusual in catalina.out file.... – KJEjava48 Apr 01 '17 at 14:13
  • @BalusC 01-Apr-2017 03:24:31.125 INFO [Thread-5] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-8080"] 01-Apr-2017 03:24:31.127 INFO [Thread-5] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-8009"] 01-Apr-2017 03:24:31.127 INFO [Thread-5] org.apache.catalina.core.StandardService.stopInternal Stopping service Catalina 01-Apr-2017 03:24:31.199 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc The web application [MyWebProject] registered the JDBC driver [com.mysql.jdbc.Driver] ... – KJEjava48 Apr 01 '17 at 14:16
  • @BalusC but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered. 01-Apr-2017 03:24:31.200 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [MyWebProject] 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. – KJEjava48 Apr 01 '17 at 14:16
  • my production tomcat restarts it self after this warning so its reallly sever with memory leaks hard to trace – shareef May 14 '17 at 18:20
  • This is not right. Threads remain open as you can see with jstack. – abarazal Jan 24 '19 at 17:06
  • why suggest to move mysql lib to /lib? Should be in webapp lib directory.. unless there is a reason to move to the CATALINA_HOME. – Jasonw Jul 01 '20 at 08:30
  • @Jasonw: to utilize server-managed connection pooling. Related: https://stackoverflow.com/q/2299469 – BalusC Jul 01 '20 at 09:25
170

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);
    }
}
Miss Chanandler Bong
  • 4,081
  • 10
  • 26
  • 36
ae6rt
  • 2,668
  • 3
  • 24
  • 25
  • 3
    It works! http://www.javabeat.net/servletcontextlistener-example/ may help to implement servlet context listener – Vadim Zin4uk Dec 04 '13 at 12:44
  • 22
    This is potentially unsafe in a shared environment as you might not want to deregister _all_ JDBC drivers that are available. See [my answer](http://stackoverflow.com/a/23912257/889583) for a safer approach. – daiscog May 28 '14 at 13:01
100

Although Tomcat does forcibly deregister the JDBC driver for you, it is nonetheless good practice to clean up all resources created by your webapp on context destruction in case you move to another servlet container which doesn't do the memory leak prevention checks that Tomcat does.

However, the methodology of blanket driver deregistration is dangerous. Some drivers returned by the DriverManager.getDrivers() method may have been loaded by the parent ClassLoader (i.e., the servlet container's classloader) not the webapp context's ClassLoader (e.g., they may be in the container's lib folder, not the webapp's, and therefore shared across the whole container). Deregistering these will affect any other webapps which may be using them (or even the container itself).

Therefore, one should check that the ClassLoader for each driver is the webapp's ClassLoader before deregistering it. So, in your ContextListener's contextDestroyed() method:

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<Driver> 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);
        }
    }
}
daiscog
  • 11,441
  • 6
  • 50
  • 62
  • Shouldn't be `if (cl.equals(driver.getClass().getClassLoader())) {` ? – user11153 May 28 '14 at 13:13
  • 7
    @user11153 No, we are checking if it is precisely the same ClassLoader instance, not if it is two separate instances which are equal in value. – daiscog May 28 '14 at 13:18
  • 6
    Although the others seem to correctly handle the problem in question, they cause problems when the war file is deleted and then replaced. In that case the drivers are de-registered and never return - only a Tomcat restart can get you out of that hole. This solution avoids that hell. – OldCurmudgeon Jul 02 '14 at 13:50
  • Here mostly same but with additional MySQL/MariaDB handling code https://github.com/spring-projects/spring-boot/issues/2612 – gavenkoa Dec 19 '15 at 09:59
  • 2
    If you use H2 or PostgreSQL this results in the driver not getting registered again upon reload. Both drivers maintain an internal registration state that isn't cleared if the driver is just deregistered from the `DriverManager`. I left a more detailed comment at https://github.com/spring-projects/spring-boot/issues/2612#issuecomment-401264199 – Marcel Stör Jun 29 '18 at 06:51
  • @MarcelStör You are right, I got trouble using the double-hash-functionality in tomcat. A rollback to the original war-version fail because the driver is not available anymore. – Grim Jun 21 '19 at 09:08
28

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...

kenor
  • 1,888
  • 2
  • 16
  • 27
sparkyspider
  • 13,195
  • 10
  • 89
  • 133
  • It looks so lovely when your application ends and your logs just say: [INFO]Shutting down application. [INFO]Closing connection pool. [INFO]Deregistering MySQLDriver. [INFO]Closing Log FileHandler. – sparkyspider Oct 19 '11 at 11:20
  • 4
    But `DataSource` does NOT have a `close` method – Jim Apr 04 '12 at 08:16
  • Yes, there is no method close() for DataSource. – Sangram Anand Jul 10 '12 at 06:30
  • [BasicDataSource](http://commons.apache.org/dbcp/api-1.2.2/org/apache/commons/dbcp/BasicDataSource.html) has a close() – PhilJ Jan 21 '13 at 14:41
  • Funnily enough, it was there in the version I was using :) Removed it as it's no longer there. The dataSource = null will do the trick instead. – sparkyspider Jan 21 '13 at 15:49
  • 9
    should it be implements javax.servlet.ServletContextListener, not extends ApplicationContextListener? – egaga Mar 23 '13 at 16:54
  • 2
    Is there a reason for the order of those operations in the method `contextDestroyed`? Why do you do step 1. before doing step 2., where `initContext`, `envContext` and `datasource` are not referenced at all? I'm asking because I don't understand step 3. – matthaeus Sep 23 '13 at 12:02
  • 4
    @matthaeus I think Step 1. is not necessary, `lookup` seems to just gets some objects you don't need. Step 3. is completly useless. It certainly doesn't add any safety and looks like something beginners would do who don't understand how GC works. I would just go with http://stackoverflow.com/a/5315467/897024 and remove all drivers. – kapex Oct 02 '13 at 15:53
  • 4
    @kapep Removing all drivers is dangerous as some might be shared across the container. See [my answer](http://stackoverflow.com/a/23912257/889583) for an approach which only removes the drivers loaded by your webapp's ClassLoader. – daiscog May 28 '14 at 13:07
14

This is purely driver registration/deregistration issue in mysql`s driver or tomcats webapp-classloader. Copy mysql driver into tomcats lib folder (so its loaded by jvm directly, not by tomcat), and message will be gone. That makes mysql jdbc driver to be unloaded only at JVM shutdown, and noone cares about memory leaks then.

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
  • 2
    that don't works... I tried to copy the jdbc driver has you say: TOMCAT_HOME/lib/postgresql-9.0-801.jdbc4.jar - Tomcat 7.0\lib\postgresql-9.0-801.jdbc4.jar with no results... – FAjir Jun 17 '11 at 12:50
  • 6
    @Florito - you have to remove it from your web-apps WEB-INF/lib as well – Collin Peters Jul 05 '11 at 16:20
8

If you are getting this message from a Maven built war change the scope of the JDBC driver to provided, and put a copy of it in the lib directory. Like this:

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.18</version>
  <!-- put a copy in /usr/share/tomcat7/lib -->
  <scope>provided</scope>
</dependency>
TimP
  • 925
  • 1
  • 8
  • 13
8

Solution for per-app deployments

This is a listener I wrote to solve the problem: it autodetects if the driver has registered itself and acts accordingly.it

Important: it is meant to be used ONLY when the driver jar is deployed in WEB-INF/lib, not in the Tomcat /lib, as many suggest, so that each application can take care of its own driver and run on a untouched Tomcat. That is the way it should be IMHO.

Just configure the listener in your web.xml before any other and enjoy.

add near the top of web.xml:

<listener>
    <listener-class>utils.db.OjdbcDriverRegistrationListener</listener-class>    
</listener>

save as utils/db/OjdbcDriverRegistrationListener.java:

package utils.db;

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import oracle.jdbc.OracleDriver;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Registers and unregisters the Oracle JDBC driver.
 * 
 * Use only when the ojdbc jar is deployed inside the webapp (not as an
 * appserver lib)
 */
public class OjdbcDriverRegistrationListener implements ServletContextListener {

    private static final Logger LOG = LoggerFactory
            .getLogger(OjdbcDriverRegistrationListener.class);

    private Driver driver = null;

    /**
     * Registers the Oracle JDBC driver
     */
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        this.driver = new OracleDriver(); // load and instantiate the class
        boolean skipRegistration = false;
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            if (driver instanceof OracleDriver) {
                OracleDriver alreadyRegistered = (OracleDriver) driver;
                if (alreadyRegistered.getClass() == this.driver.getClass()) {
                    // same class in the VM already registered itself
                    skipRegistration = true;
                    this.driver = alreadyRegistered;
                    break;
                }
            }
        }

        try {
            if (!skipRegistration) {
                DriverManager.registerDriver(driver);
            } else {
                LOG.debug("driver was registered automatically");
            }
            LOG.info(String.format("registered jdbc driver: %s v%d.%d", driver,
                    driver.getMajorVersion(), driver.getMinorVersion()));
        } catch (SQLException e) {
            LOG.error(
                    "Error registering oracle driver: " + 
                            "database connectivity might be unavailable!",
                    e);
            throw new RuntimeException(e);
        }
    }

    /**
     * Deregisters JDBC driver
     * 
     * Prevents Tomcat 7 from complaining about memory leaks.
     */
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        if (this.driver != null) {
            try {
                DriverManager.deregisterDriver(driver);
                LOG.info(String.format("deregistering jdbc driver: %s", driver));
            } catch (SQLException e) {
                LOG.warn(
                        String.format("Error deregistering driver %s", driver),
                        e);
            }
            this.driver = null;
        } else {
            LOG.warn("No driver to deregister");
        }

    }

}
Andrea Ratto
  • 815
  • 1
  • 11
  • 23
  • Tip: As of Servlet 3.0, you can annotate your class with [`@WebListener`](http://docs.oracle.com/javaee/7/api/javax/servlet/annotation/WebListener.html) and omit the `web.xml` configuration. – Basil Bourque May 12 '16 at 03:02
  • True, just make sure that it is picked up with a priority high enough, so that no one needs to use the driver before or after. – Andrea Ratto Aug 24 '16 at 01:32
7

I found that implementing a simple destroy() method to de-register any JDBC drivers works nicely.

/**
 * Destroys the servlet cleanly by unloading JDBC drivers.
 * 
 * @see javax.servlet.GenericServlet#destroy()
 */
public void destroy() {
    String prefix = getClass().getSimpleName() +" destroy() ";
    ServletContext ctx = getServletContext();
    try {
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while(drivers.hasMoreElements()) {
            DriverManager.deregisterDriver(drivers.nextElement());
        }
    } catch(Exception e) {
        ctx.log(prefix + "Exception caught while deregistering JDBC drivers", e);
    }
    ctx.log(prefix + "complete");
}
animuson
  • 53,861
  • 28
  • 137
  • 147
  • 6
    This is potentially unsafe in a shared environment as you might not want to deregister _all_ JDBC drivers that are available. See [my answer](http://stackoverflow.com/a/23912257/889583) for a safer approach. Also, this really should be done in a ServletContextListener, not on a per-servlet basis as your JDBC driver is shared across all of your servlets in your webapp. – daiscog May 28 '14 at 13:14
6

I will add to this something I found on the Spring forums. If you move your JDBC driver jar to the tomcat lib folder, instead of deploying it with your webapp, the warning seems to disappear. I can confirm that this worked for me

http://forum.springsource.org/showthread.php?87335-Failure-to-unregister-the-MySQL-JDBC-Driver&p=334883#post334883

Collin Peters
  • 4,353
  • 3
  • 29
  • 36
  • 1
    I think this offers a better solution - just subclass your DatasourceManager and override the close method to add deregistration. Then Spring will handle it when it destroys its context, and Tomcat won't give you the SEVERE log, and you don't have to move your JDBC driver into the lib dir. [Here's the orignal msg from the old spring forum](http://forum.spring.io/forum/spring-projects/security/96659-spring-security-jdbc-memory-leak) – Adam Sep 24 '14 at 12:42
4

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.

King-Wizard
  • 15,628
  • 6
  • 82
  • 76
2

I was having a similar problem, but additionally I was getting a Java Heap Space error anytime I modified/saved JSP pages with Tomcat server running, therefore the context were not fully recharged.

My versions were Apache Tomcat 6.0.29 and JDK 6u12.

Upgrading JDK to 6u21 as suggested in References section of URL http://wiki.apache.org/tomcat/MemoryLeakProtection solved the Java Heap Space problem (context now reloads OK) although JDBC Driver error still appears.

Francisco Alvarado
  • 2,815
  • 2
  • 26
  • 51
0

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.

Bharat
  • 109
  • 1
  • 1
  • 8
0

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 .

AT82
  • 71,416
  • 24
  • 140
  • 167
PyDevSRS
  • 1,715
  • 16
  • 17
0

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

cantoni
  • 2,912
  • 2
  • 17
  • 24