Oracle driver memory leak - Tomcat

2019-02-13 18:32发布

问题:

We're using tomcat-7.0.33. Spring 3.0.1 and JPA using a tomcat JNDI datasource. Oracle 10g on the backend using ojdbc6.jar (latest).

When we try to undeploy the application some Oracle classes seem to be leaking. I don't see this when using the older ojdbc14.jar drivers but we can't use those as we're migrating to Oracle 11g which requires the newer drivers. I'm guessing this is a bug in the Oracle drivers? Is there anything I can do to clean these resources up? I've tried closing the database connection pool and other things to no avail...

Would I be better off not using Tomcat's connection pool? We'd rather have the server connecting to the database but we could do our own if necessary...

Server console shows:

17505 INFO org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'myManager' 17515 INFO org.apache.tiles.access.TilesAccess - Removing TilesContext for context: org.springframework.web.servlet.view.tiles2.SpringTilesApplicationContextFactory$SpringWildcardServletTilesApplicationContext Dec 06, 2012 6:41:29 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks SEVERE: The web application [/myApp] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@1468544]) and a value of type [java.lang.Class] (value [class oracle.sql.AnyDataFactory]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. Dec 06, 2012 6:41:29 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks SEVERE: The web application [/myApp] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@d73b31]) and a value of type [java.lang.Class] (value [class oracle.sql.TypeDescriptorFactory]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. Dec 06, 2012 6:41:29 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks SEVERE: The web application [/myApp] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@13aae39]) and a value of type [java.lang.Class] (value [class oracle.sql.TypeDescriptorFactory]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. Dec 06, 2012 6:41:29 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks SEVERE: The web application [/myApp] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@18443b1]) and a value of type [java.lang.Class] (value [class oracle.sql.AnyDataFactory]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. Dec 06, 2012 6:41:34 PM org.apache.catalina.startup.HostConfig deleteRedeployResources INFO: Undeploying context [/myApp]

I have tried adding a ContextListener to close our DBCP connection manually but that didn't help.

InitialContext initial = new InitialContext();

DataSource ds = (DataSource) initial.lookup("java:/comp/env/jdbc/myDS");

if (ds.getConnection() == null) {
    throw new RuntimeException("I failed to find the datasource");
}

LOG.debug("Found datasource.  Closing...");
BasicDataSource bds = (BasicDataSource) ds;

bds.close();

回答1:

Figured out the issue... Toni had a good suggestion (but de-registering the driver meant that when the app reloaded the driver was no longer available!).

In our case we were accidentally including ojdbc6.jar with our web app AND in the Tomcat/lib directory. This pressumably caused Tomcat to use our classloader to create objects. Thus when our application was being unloaded Tomcat's DBCP pool still had open handles to classes in our application.

Removing ojdbc6.jar from our WEB-INF/lib solved the problem.



回答2:

In the listener you have also to de-register the JDBC driver (i.e. ojdbc5.jar or what you are using).

See this SO question for the code snippet.