score:36
THE SOLUTION (tl;dr)
In order to solve this issue, add an attribute closeMethod
(documented here) with the value "close" to the Resource element in the context.xml file.
Here's the correct content of my /META-INF/context.xml file:
<Context>
<!-- Configuration for the Tomcat JDBC Connection Pool -->
<Resource name="jdbc/someDB"
type="javax.sql.DataSource"
auth="Container"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://localhost:5432/somedb"
username="postgres"
password="12345"
maxActive="100"
minIdle="10"
initialSize="10"
validationQuery="SELECT 1"
validationInterval="30000"
removeAbandoned="true"
removeAbandonedTimeout="60"
abandonWhenPercentageFull="50"
closeMethod="close" />
</Context>
Pay attention to the attribute closeMethod. I tested it and now the number of connections are kept STRICTLY as defined in the context.xml file!
NOTE
There is one moment (related to JNDI) that may be taken care of. See the UPDATE 3 for the complete description.
Long answer
OK, I found the above solution thanks to Apache Tomcat committor Konstantin Kolinko. I reported this issue as an Apache Tomcat bug on ASF Bugzilla and it turned out it's not a bug (see UPDATE 1).
=== UPDATE 1 (2012-12-03) aka "A New Hope" ===
Well, it still turned out to be a bug. Mark Thomas, the Apache Tomcat 7 release manager, confirmed that (quote):
"This is a memory leak bug in jdbc-pool. PoolCleaner instances are retaining references to the ConnectionPool preventing it from being GC'd.
...
This has been fixed in trunk and 7.0.x and will be included in 7.0.34 onwards."
So if you have an older Tomcat version (less than 7.0.34), use the above solution, otherwise, starting with Apache Tomcat version 7.0.34, there should be no issues like the one I described. (see UPDATE 2)
=== UPDATE 2 (2014-01-13) aka "The Issue Strikes Back" ===
It seems like the issue initially described in my bug report is still present even for the currently latest Apache Tomcat version 7.0.50 and I also reproduced it with Tomcat 7.0.47 (thanks to Miklos Krivan for pointing it out). Although now Tomcat sometimes manages to close additional connections after reloading, and sometimes the number of connections are increased after one reload and then kept steady, but eventually this behavior is still not reliable.
I still could reproduce the initially described issue (although again not that easy: it may be related to the frequency of successive reloads). Seems like it's just a matter of time, i.e. if Tomcat has enough time after reload, it manages the connection pool more or less as it should. As Mark Thomas mentioned in his comment (quote): "As per the docs for closeMethod, that method exists solely to speed up the freeing of resources that would otherwise be freed by GC." (end of quote), and it looks like the speed is the defining factor.
When using the solution presented by Konstantin Kolinko (to use closeMethod="close") everything WORKS just fine, and the number of connections reserved are kept STRICTLY as defined in the context.xml file. So it appears that using closeMethod="close" is the ONLY true way (at the moment) to avoid running out of connections after context reloading.
=== UPDATE 3 (2014-01-13) aka "Return of the Tomcat Release Manager" ===
The mystery behind the behavior described in the UPDATE 2 is solved. More details have been cleared now after I received a reply from Mark Thomas (Tomcat release manager). I hope this is the last update. So the bug was indeed fixed as was mentioned in the UPDATE 1. I am posting the essential part from Mark's reply here as a quote (emphasis mine):
The actual memory leak found while investigating this bug has been fixed in 7.0.34 onwards as per comments #4 to #6.
The issue of the connections not being closed on reload is a result of the J2EE specification for JNDI resources and this part of the bug report is therefore invalid. I am restoring the state of this bug to fixed to reflect that the memory leak that did exist has been fixed.
To expand on why the failure to immediately close connection after reload is invalid, the J2EE specification provides no mechanism for the container to tell the resource it is no longer required. Therefore all the container can do is clear references to the resource and wait for garbage collection (which will trigger the closure of the pool and the associated connections). Garbage collection occurs at times determined by the JVM so this is why it takes an indeterminate amount of time for connections to be closed after a context reload as a garbage collection may not occur for some time.
Tomcat has added the Tomcat specific JNDI attribute closeMethod which can be used to trigger the explicit close of a JNDI resource when a context is stopped. If waiting for GC to clean up resources is not acceptable then simply use this parameter. Tomcat does not use this by default as it may have unexpected and unwanted side-effects for some JNDI resources.
If you'd like to see a standard mechanism provided for telling JNDI resources that they are no longer required then you need to lobby the J2EE expert group.
Conclusion
Just use the solution presented in the beginning of this post (but, just in case, keep in mind the JNDI related issue that can theoretically arise from using it).
Alternative solution
Michael Osipov suggested using his CloseableResourceListener, which prevents memory leaks caused by left open resources during undeployment of web applications. So you may also give it a try.
DISCLAIMER
The aliases for the UPDATES were inspired by the Star Wars film series. All rights belong to their respective owners.
Source: stackoverflow.com
Related Query
- JDBC connection pool runs out of connections when Context reload="true" is enabled in Tomcat
- Connection timed out when trying to make a simple Http GET request
- Close connections in pool/cache (cache created with singleton) when Eclipse reloads context
- The code when run opens the jdbc connection but it is not printing the table data.What is wrong with this code?
- JDBC runs fine when libraries extracted into runnable jar, but not when they are just packaged
- how to set connection pool in context file?
- Why does heap space run out only when running JUnit tests?
- Eclipse runs debug mode even when I click "run"
- "Unable to locate JAR/zip" error for JDBC connections [BIRT Eclipse, Windows 7, Oracle 11g]
- Unable to open JDBC Connection for DDL execution
- How to enable "Browse Deployment Location..." context menu item in Eclipse?
- How to debug Java code when it is out of sync?
- Eclipse runs out of heap space on ant build
- Tomcat in Eclipse: It runs but time out during startup anyway
- Remote Debugging: Failed to connect to remote VM. Connection timed out
- "Timed out waiting for ad response", when trying add admob into my application
- When using Mylyn in Eclipse, why do task context elements not show up in the navigator view?
- How to solve the connection when install aws toolkit on eclipse Neon?
- How do I make an Eclipse plugin extension which displays different context menu items when the user clicks a marker?
- Getting "Launch error: Failed to connect to remote VM. Connection timed out" when trying to debug my app on my device in android
- Failed to connect to remote VM. Connection refused. when trying to debug remote java application in Flash Builder 4.7
- Eclipse giving error when adding MySql jdbc driver
- SSl Handshake validation error in connection to SQL Server by JDBC driver
- Eclipse runs out of handles
- eclipse hangs when run application (application runs fine, eclipse is what hangs)
- Out of Memory (java heap) when running suite with too many test cases
- pom.xml greyed out when importing maven project into eclipse
- how to stop losing focus when something is printed out to eclipse Console View?
- How do I setup Connection Pool with GWT/Jetty in eclipse?
- why java code coverage still show yellow color when enable assertions
More Query from same tag
- I am developing simple Rest service which will return simple "Hello", but i am unable to run that on tomcat server
- When selenium standalone jar is required?
- Testing a Java Long value in an if statement. Does 0 != 0
- Eclipse changes to PHP perspective after running code in Java
- How can I change the representation of 2-dimensional arrays in the debugging mode of eclipse?
- TeXlipse spell-check configuration
- Missing appengine-api-labs.jar and other required libraries
- SVNKit for Eclipse
- Are openshift and pydev really full compatible?
- Eclipse Jetty Integration, how to setup dependencies?
- What are .jazzignore files?
- Hard wrap string literals at print margin in Eclipse C/C++
- Setting usesCleartextTraffic in Eclipse Android project
- Unable to resolve target 'android-8'
- Distributed Revision Control with automatic synchronization or Eclipse plugin better than FileSync?
- Error in XML file making R not work
- Modification in Java file, is it required to run ndk-build every time?
- Maven builds project with Java 1.6 even if 1.5 is specified
- Access is Denied, Issue in embedded Derby
- Eclipse rebinding delete line to ctrl+shift+d does not work
- How to import git java project to Eclipse
- MobileFirst Build not update JS and HTML changes
- Get list of packages in a java project
- Eclipse on MAC, set current directory to be in Documents folder not APP BUNDLE
- How to make eclipse error parser accept cilk_for
- Eclipse: change name of existing package with classes inside
- Eclipse with Tomcat 8 and maven crash only after 1 minute
- Why does my Eclipse different highlight rules to .xml and android's .xml?
- Eclipse plugin : Get the enclosing class and member name
- Can I have more than one class containing the main() method in a Java project?