Add a workaround for a common cause of locked files.
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Wed, 28 Oct 2009 19:25:31 +0000 (19:25 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Wed, 28 Oct 2009 19:25:31 +0000 (19:25 +0000)
git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@830736 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java
java/org/apache/catalina/core/LocalStrings.properties

index 8ffa3ee..dd8bf54 100644 (file)
 
 package org.apache.catalina.core;
 
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+
 import javax.imageio.ImageIO;
 
 import org.apache.catalina.Lifecycle;
 import org.apache.catalina.LifecycleEvent;
 import org.apache.catalina.LifecycleListener;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.res.StringManager;
 
 /**
- * Provide a workaround for known places where the Java Runtime environment uses
+ * Provide a workaround for known places where the Java Runtime environment can
+ * cause a memory leak or lock files.
+ * <p>
+ * Memory leaks occur when JRE code uses
  * the context class loader to load a singleton as this will cause a memory leak
  * if a web application class loader happens to be the context class loader at
  * the time. The work-around is to initialise these singletons when Tomcat's
  * common class loader is the context class loader.
+ * <p>
+ * Locked usually files occur when a resource inside a JAR is accessed without
+ * first disabling Jar URL connection caching. The workaround is to disable this
+ * caching by default. 
  */
 public class JreMemoryLeakPreventionListener implements LifecycleListener {
 
+    protected static final Log log =
+        LogFactory.getLog(JreMemoryLeakPreventionListener.class);
+    protected static final StringManager sm =
+        StringManager.getManager(Constants.Package);
+    
     @Override
     public void lifecycleEvent(LifecycleEvent event) {
         // Initialise these classes when Tomcat starts
@@ -42,7 +62,6 @@ public class JreMemoryLeakPreventionListener implements LifecycleListener {
              * 
              * Those libraries / components known to trigger memory leaks due to
              * eventual calls to getAppContext() are:
-             * 
              * - Google Web Toolkit via its use of javax.imageio
              * - Tomcat via its use of java.beans.Introspector.flushCaches() in
              *   1.6.0_15 onwards
@@ -54,6 +73,31 @@ public class JreMemoryLeakPreventionListener implements LifecycleListener {
             // issue.
             ImageIO.getCacheDirectory();
             
+            /*
+             * Several components end up opening JarURLConnections without first
+             * disabling chaching. This effectively locks the file. Whilst more
+             * noticeable and harder to ignore on Windows, it affects all
+             * operating systems.
+             * 
+             * Those libraries/components known to trigger this issue include:
+             * - log4j versions 1.2.15 and earlier
+             * - javax.xml.bind.JAXBContext.newInstance()
+             */
+            
+            // Set the default JAR URL caching policy to not to cache
+            try {
+                // Doesn't matter that this JAR doesn't exist - just as long as
+                // the URL is well-formed
+                URL url = new URL("jar:file://dummy.jar!/dummy.txt");
+                URLConnection uConn = url.openConnection();
+                uConn.setDefaultUseCaches(false);
+            } catch (MalformedURLException e) {
+                log.error(sm.getString(
+                        "jreLeakListener.jarUrlConnCacheFail"), e);
+            } catch (IOException e) {
+                log.error(sm.getString(
+                "jreLeakListener.jarUrlConnCacheFail"), e);
+            }
         }
     }
 
index 4d02b66..5fbad19 100644 (file)
@@ -65,6 +65,7 @@ httpEngineMapper.container=This container is not a StandardEngine
 httpHostMapper.container=This container is not a StandardHost
 interceptorValve.alreadyStarted=InterceptorValve has already been started
 interceptorValve.notStarted=InterceptorValve has not yet been started
+jreLeakListener.jarUrlConnCacheFail=Failed to disable Jar URL connection caching by default
 naming.wsdlFailed=Failed to find wsdl file: {0}
 naming.bindFailed=Failed to bind object: {0}
 naming.jmxRegistrationFailed=Failed to register in JMX: {0}