Bug #45577 Undeploy application still hold lock to mysql-connector-java.jar
Submitted: 18 Jun 2009 5:48 Modified: 27 Jan 2012 7:26
Reporter: Vlad Skarzhevskyy Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / J Severity:S3 (Non-critical)
Version:5.1.7 OS:Windows (Win XP sp3)
Assigned to: Philip Olson CPU Architecture:Any

[18 Jun 2009 5:48] Vlad Skarzhevskyy
Description:
After upgrade from 5.1.5 to 5.1.6 web application fails to undeploy properly.
The mysql jdbc jar file still locked.

Also tested with mysql-connector-java 5.1.7 the same problem.
Java Profiler shows that some com.mysql.jdbc classes are still used. and not garbage collected.

We do call java.sql.DriverManager.deregisterDriver(..) in ServletContextListener.contextDestroyed() so undeploy worked fine with older versions.

-- 
The most annoying problem (May be clue) is even if application is using oracle jdbc the mysql-connector jar is still locked after web application is undeplyed.
(We do have this two drivers included in war)

---
Environment: Win XP or Server 2003, SUN Java 1.6 or JRockit_160_05, Apache Tomcat/6.0.20

How to repeat:
Web application mysql-connector-java.jar included in WEB-INF\lib
Start web application in Tomcat 6.  
     it should connect to db using any JDBC driver.
Undeploy application
The only file remaining from the application is mysql-connector-java.jar

----
I can help to create small testing web application or whatever required.
[18 Jun 2009 9:47] Tonci Grgin
Hi Vlad and thanks for your report.

> Java Profiler shows that some com.mysql.jdbc classes are still used. and not garbage collected.

Tuning GC is an art in itself... Did you tried more aggressive settings or parallel GC?

>How to repeat: Web application mysql-connector-java.jar included in WEB-INF\lib

What is this "WEB-INF\lib" you're talking about? Did you tried creating stand-alone test case (no Apache and such)? Have you tried setting "holdResultsOpenOverStatementClose" to false?

Please attach small but complete test case demonstrating unwanted behavior.
[18 Jun 2009 13:10] Vlad Skarzhevskyy
Empty Web application sources maven build

Attachment: sql-web-app-sources.zip (application/zip, text), 2.51 KiB.

[18 Jun 2009 13:14] Tonci Grgin
Vlad, I am sorry but I still don't see a valid test case in your attachment... Am I missing something here?
[18 Jun 2009 13:17] Vlad Skarzhevskyy
Created and Empty web application to show the bug!

Nothing in the war but mysql jar!!!!! Not even opening connection to Any DB!

Maven2 build file:
http://pyx4j.com/downloads/mysql/sql-web-app-sources.zip

Resulting war
http://pyx4j.com/downloads/mysql/sql-web-app.war
[18 Jun 2009 13:25] Vlad Skarzhevskyy
Hi Tonci
  The valid test is deploy war on Tomcat and then undeply it!  All on Windows! On Linux it may work properly since it has different file locking....

 Also regarding your previous comments:
1)  WEB-INF\lib   is a special directory in war archive where all there required for web application jar are going.  

2) The GC configuration may have nothing to do with this.
 In profiler I see that classes are references by root class loader and not the instances of the classes.  Will add the picture in next upload.
[18 Jun 2009 14:03] Vlad Skarzhevskyy
I did some profiling, for this DriverManager.deregisterDriver has been added to application: http://pyx4j.com/downloads/mysql/sql-web-app-all-4-profiler.zip

I can't see any mysql instance or classes been retained after the app is stopped and undeployed.

Definitely you have some unclosed resources that are loaded from jar...
I would try to find them if I can.

But honestly do you need this exercise? Can you find from the changes in source
from version 5.1.5 to 5.1.6  what has been changed to live lock on the jar

If you have url.url.openConnection()  from  the jar then this will lock the jar!
Call it JVM bug but there is a work around this:

-----
InputStream input = null;
try {
    URLConnection connection = url.openConnection();
    if (connection instanceof JarURLConnection) {
        ((JarURLConnection) connection).setUseCaches(false);
    }
    input = connection.getInputStream();
    .. DO your job 
} finally {
    if(input != null) {
        try {
            input.close();
        } catch (Throwable ignore) {
        }
    }
} 
-----
[20 Jun 2009 9:40] Tonci Grgin
Jess will follow up on this.
[20 Jun 2009 9:43] Tonci Grgin
Vlad, we think this could be related to (see 5.1.6 change log):
    - Fixed issue where META-INF in the binary .jar file wasn't packed correctly,
      leading to failure of the JDBC-4.0 SPI mechanism.
but Jess will know more.
[22 Jun 2009 4:03] Jess Balint
Verified as described. Workaround is to use "antiResourceLocking=true" as a Tomcat Context attribute.
[25 Sep 2009 16:14] Ed S
I have the same problem on v5.1.9.  I understand the workaround is to use "antiResourceLocking=true" in the tomcat context.xml file.  However, I will be deploying to a web hosting center of which I do not have access to make system configuration changes.  Also, some of the documentation I've been reading says to put the jdbc driver jar file in the tomcat putting the jdbc driver in common/lib for tomcat.  This doesn't work for hosting centers where you do not have that level of access.
Is there another workaround for this?
Note: I have already tried the ContextListener contextDestroyed method to DriverManger.deregisterDriver, as well as another tip I found about a timer needing to be cancelled.  Please help
[23 Jul 2010 11:55] Matthijs Bierman
The workaround isn't a very good solution, as this will cause very slow startup of applications on Windows (it needs to copy all the JARs to a temp directory).

It will probably also cause file handle leaks if you redeploy with the workaround. And once you run out of file handles you can restart your server...
[4 Aug 2010 20:05] Pascal Emmanuelli
I think that it's rather the auto-Loading of drivers in JDBC 4.0 which is to blame than the mysql jar. We have exactly the same problem, and the only drivers jars locked by the server are those containing META-INF/service/java.sql.Driver (those of posgresQL and mysql, in our case, knowing that we only use the mysql one in our application). The jars of oracle, hsqldb and sql server (without this file) are not affected by the problem.
And it's really an initialization problem, because it occurs even with customized  DataSource and ClassLoader, which doesn't call java.sql.DriverManager.
[27 Jan 2012 7:26] Philip Olson
This has now been documented, thanks to this report and comments:

Note that the auto-loading of drivers having the
META-INF/service/java.sql.Driver class in
JDBC 4.0 causes an improper deployment of the Connector/J driver
in Tomcat on Windows. Namely, the Connector/J jar remains locked.
This is an initialization problem that is not related to the
driver. The possible workarounds, if viable, are as follows: use
"antiResourceLocking=true" as a Tomcat Context
attribute, or remove the META-INF/ directory.