views:

22

answers:

1

I'm using Eclipse to develop a java web app and My IT department called and said I had over 75 open oracle connections to the development Oracle Server originating from my PC. The deployed app has been using the same singleton connection bean for a year now and I haven't had any trouble with exceeding connections there. IT even connfirmed I only had 4 open connections on the deployment server. Something is going on when I develop locally in Eclipse.

Looking at the console debug output, everything looks good on initial startup

Sep 27, 2010 9:39:08 AM org.apache.catalina.startup.Catalina start
== no ConnCache Bean instance found 
== Initializing Connection Cache Data Src
== About to load the properties
== Initializing Datasource for using jdbc:oracle:thin:@hostname:port:oracle-sid
== Reading property file 
== Setting InitialLimit to 3
== Properties {TimeToLiveTimeout=4, MinLimit=4, ConnectionWaitTimeout=44, MaxLimit=5, InitialLimit=3, AbandonedConnectionTimeout=281, InactivityTimeout=269}

But then I noticed the following SEVERE message in the console When Eclipse reloads the context

Sep 27, 2010 9:40:38 AM org.apache.catalina.core.StandardContext reload
INFO: Reloading this Context has started
Sep 27, 2010 9:40:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The 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.
Sep 27, 2010 9:40:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [] appears to have started a thread named [Thread-9] but has failed to stop it. 
This is very likely to create a memory leak.

I'm guessing that Eclipse is recreating a connection cache everytime the it reloads the context and the old connections and cache are not getting destroyed. How can I get Eclipse to terminate the cache or close all previous connections when the context is reloaded. I can post my connectionBean class if necessary.

A: 

It appears that you are leaking memory via the unclosed connections of the previous version of the application. This is quite possible if you've chosen to perform automatic publishing of your web application from Eclipse to Tomcat.

Tomcat will discard the current classloader of the web application, when it attempts to perform a reload. All objects from this GC root (the classloader), that will still be held, will not be garbage collected. Due to the presence of the singleton (I'm assuming that the singleton stores a DataSource object or is maintaining a pool of Connection objects), these Connection objects will never be treated as unreachable objects, and hence, will not be eligible for GC.

In the short run, you can do the following:

  • If you can help it, restart Tomcat whenever you need to publish a new version of the application.
  • Implement a ServletContextListener, and attempt to discard the singleton reference when the servlet (application) context is destroyed. This makes the singleton object unreachable, and hence eligible for GC. This is recommended, for the same is bound to occur in production, unless Tomcat is restarted.

By the way, this behavior, where in singletons cause memory and hence connection leakage will occur in any application server, as long as the application is redeployed time and again without restarting the server. The only way to prevent this, is to ensure that the singleton is destroyed when the application context is destroyed.

Vineet Reynolds
@Vineet I am working on a copy of the data. We have 3 Oracle servers, dev/stage/production and I am connecting to the dev oracle server from my PC, perfectly acceptable - I am using dev oracle server as intented. Thanks for the SevlertConectextListener appraoch. I will investigate.
jeff
@jeff, well, that comment was pointless, so I removed it. I've been burnt by database restarts during a debugging session, but that need not apply to you.
Vineet Reynolds
@Vineet, I tried the SevlertConectextListener but the method contextDestroyed is not called on a Reload, only when I shut down Tomcat. And when I stop Tomcat, and the contextDestroyed method tries to discard the Singleton, the singleton no longer exists (as expected) so the listener isn't really serving a pupose. I may just change reload=false in the server.xml and manually restart the server as you suggested unless there are any other suggestions.
jeff
@jeff, ah well, I didn't expect that. You could attempt nullifying the singleton on the destroy event of a servlet (possibly a controller, if you have one), but I'm not too certain about that after this attempt made by you.
Vineet Reynolds