You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2016/05/20 11:18:56 UTC

svn commit: r1744713 - in /tomcat/trunk: java/org/apache/catalina/core/ java/org/apache/catalina/loader/ test/org/apache/catalina/loader/ webapps/docs/ webapps/docs/config/

Author: markt
Date: Fri May 20 11:18:55 2016
New Revision: 1744713

URL: http://svn.apache.org/viewvc?rev=1744713&view=rev
Log:
Remove clearReferencesStatic option

Modified:
    tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
    tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml
    tomcat/trunk/java/org/apache/catalina/loader/WebappClassLoaderBase.java
    tomcat/trunk/test/org/apache/catalina/loader/TestWebappClassLoaderWeaving.java
    tomcat/trunk/webapps/docs/changelog.xml
    tomcat/trunk/webapps/docs/config/context.xml

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=1744713&r1=1744712&r2=1744713&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Fri May 20 11:18:55 2016
@@ -713,20 +713,6 @@ public class StandardContext extends Con
     private boolean clearReferencesRmiTargets = true;
 
     /**
-     * Should Tomcat attempt to null out any static or final fields from loaded
-     * classes when a web application is stopped as a work around for apparent
-     * garbage collection bugs and application coding errors? There have been
-     * some issues reported with log4j when this option is true. Applications
-     * without memory leaks using recent JVMs should operate correctly with this
-     * option set to <code>false</code>. If not specified, the default value of
-     * <code>false</code> will be used.
-     *
-     * @deprecated This option will be removed in Tomcat 8.5
-     */
-    @Deprecated
-    private boolean clearReferencesStatic = false;
-
-    /**
      * Should Tomcat attempt to terminate threads that have been started by the
      * web application? Stopping threads is performed via the deprecated (for
      * good reason) <code>Thread.stop()</code> method and is likely to result in
@@ -2593,38 +2579,6 @@ public class StandardContext extends Con
 
 
     /**
-     * @return the clearReferencesStatic flag for this Context.
-     *
-     * @deprecated This option will be removed in Tomcat 8.5
-     */
-    @Deprecated
-    public boolean getClearReferencesStatic() {
-
-        return (this.clearReferencesStatic);
-
-    }
-
-
-    /**
-     * Set the clearReferencesStatic feature for this Context.
-     *
-     * @param clearReferencesStatic The new flag value
-     *
-     * @deprecated This option will be removed in Tomcat 8.5
-     */
-    @Deprecated
-    public void setClearReferencesStatic(boolean clearReferencesStatic) {
-
-        boolean oldClearReferencesStatic = this.clearReferencesStatic;
-        this.clearReferencesStatic = clearReferencesStatic;
-        support.firePropertyChange("clearReferencesStatic",
-                                   oldClearReferencesStatic,
-                                   this.clearReferencesStatic);
-
-    }
-
-
-    /**
      * @return the clearReferencesStopThreads flag for this Context.
      */
     public boolean getClearReferencesStopThreads() {
@@ -5077,8 +5031,6 @@ public class StandardContext extends Con
                 // created.
                 setClassLoaderProperty("clearReferencesRmiTargets",
                         getClearReferencesRmiTargets());
-                setClassLoaderProperty("clearReferencesStatic",
-                        getClearReferencesStatic());
                 setClassLoaderProperty("clearReferencesStopThreads",
                         getClearReferencesStopThreads());
                 setClassLoaderProperty("clearReferencesStopTimerThreads",

Modified: tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml?rev=1744713&r1=1744712&r2=1744713&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml (original)
+++ tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml Fri May 20 11:18:55 2016
@@ -86,10 +86,6 @@
                description="Should Tomcat look for memory leaks in RMI Targets and clear them if found as a work around for application coding errors?"
                type="boolean"/>
 
-    <attribute name="clearReferencesStatic"
-               description="Deprecated. Will be removed in Tomcat 8.5. Should Tomcat attempt to null out any static or final fields from loaded classes when a web application is stopped as a work around for apparent garbage collection bugs and application coding errors?"
-               type="boolean"/>
-
     <attribute name="clearReferencesStopThreads"
                description="Should Tomcat attempt to terminate threads that have been started by the web application? Advisable to be used only in a development environment."
                type="boolean"/>

Modified: tomcat/trunk/java/org/apache/catalina/loader/WebappClassLoaderBase.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/loader/WebappClassLoaderBase.java?rev=1744713&r1=1744712&r2=1744713&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/loader/WebappClassLoaderBase.java (original)
+++ tomcat/trunk/java/org/apache/catalina/loader/WebappClassLoaderBase.java Fri May 20 11:18:55 2016
@@ -26,7 +26,6 @@ import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
@@ -336,20 +335,6 @@ public abstract class WebappClassLoaderB
     private boolean clearReferencesRmiTargets = true;
 
     /**
-     * Should Tomcat attempt to null out any static or final fields from loaded
-     * classes when a web application is stopped as a work around for apparent
-     * garbage collection bugs and application coding errors? There have been
-     * some issues reported with log4j when this option is true. Applications
-     * without memory leaks using recent JVMs should operate correctly with this
-     * option set to <code>false</code>. If not specified, the default value of
-     * <code>false</code> will be used.
-     *
-     * @deprecated This option will be removed in Tomcat 8.5
-     */
-    @Deprecated
-    private boolean clearReferencesStatic = false;
-
-    /**
      * Should Tomcat attempt to terminate threads that have been started by the
      * web application? Stopping threads is performed via the deprecated (for
      * good reason) <code>Thread.stop()</code> method and is likely to result in
@@ -543,32 +528,6 @@ public abstract class WebappClassLoaderB
 
 
     /**
-     * Return the clearReferencesStatic flag for this Context.
-     * @return <code>true</code> if the classloader should attempt to set to null
-     *    static final fields in loaded classes
-     *
-     * @deprecated This option will be removed in Tomcat 8.5
-     */
-    @Deprecated
-    public boolean getClearReferencesStatic() {
-        return (this.clearReferencesStatic);
-    }
-
-
-    /**
-     * Set the clearReferencesStatic feature for this Context.
-     *
-     * @param clearReferencesStatic The new flag value
-     *
-     * @deprecated This option will be removed in Tomcat 8.5
-     */
-    @Deprecated
-    public void setClearReferencesStatic(boolean clearReferencesStatic) {
-        this.clearReferencesStatic = clearReferencesStatic;
-    }
-
-
-    /**
      * @return the clearReferencesStopThreads flag for this Context.
      */
     public boolean getClearReferencesStopThreads() {
@@ -704,7 +663,6 @@ public abstract class WebappClassLoaderB
         base.resources = this.resources;
         base.delegate = this.delegate;
         base.state = LifecycleState.NEW;
-        base.clearReferencesStatic = this.clearReferencesStatic;
         base.clearReferencesStopThreads = this.clearReferencesStopThreads;
         base.clearReferencesStopTimerThreads = this.clearReferencesStopTimerThreads;
         base.clearReferencesLogFactoryRelease = this.clearReferencesLogFactoryRelease;
@@ -1560,12 +1518,6 @@ public abstract class WebappClassLoaderB
             clearReferencesRmiTargets();
         }
 
-        // Null out any static or final fields from loaded classes,
-        // as a workaround for apparent garbage collection bugs
-        if (clearReferencesStatic) {
-            clearReferencesStaticFinal();
-        }
-
          // Clear the IntrospectionUtils cache.
         IntrospectionUtils.clear();
 
@@ -1645,131 +1597,6 @@ public abstract class WebappClassLoaderB
         }
     }
 
-
-    private final void clearReferencesStaticFinal() {
-
-        Collection<ResourceEntry> values = resourceEntries.values();
-        Iterator<ResourceEntry> loadedClasses = values.iterator();
-        //
-        // walk through all loaded class to trigger initialization for
-        //    any uninitialized classes, otherwise initialization of
-        //    one class may call a previously cleared class.
-        while(loadedClasses.hasNext()) {
-            ResourceEntry entry = loadedClasses.next();
-            if (entry.loadedClass != null) {
-                Class<?> clazz = entry.loadedClass;
-                try {
-                    Field[] fields = clazz.getDeclaredFields();
-                    for (int i = 0; i < fields.length; i++) {
-                        if(Modifier.isStatic(fields[i].getModifiers())) {
-                            fields[i].get(null);
-                            break;
-                        }
-                    }
-                } catch(Throwable t) {
-                    // Ignore
-                }
-            }
-        }
-        loadedClasses = values.iterator();
-        while (loadedClasses.hasNext()) {
-            ResourceEntry entry = loadedClasses.next();
-            if (entry.loadedClass != null) {
-                Class<?> clazz = entry.loadedClass;
-                try {
-                    Field[] fields = clazz.getDeclaredFields();
-                    for (int i = 0; i < fields.length; i++) {
-                        Field field = fields[i];
-                        int mods = field.getModifiers();
-                        if (field.getType().isPrimitive()
-                                || (field.getName().indexOf('$') != -1)) {
-                            continue;
-                        }
-                        if (Modifier.isStatic(mods)) {
-                            try {
-                                field.setAccessible(true);
-                                if (Modifier.isFinal(mods)) {
-                                    if (!((field.getType().getName().startsWith("java."))
-                                            || (field.getType().getName().startsWith("javax.")))) {
-                                        nullInstance(field.get(null));
-                                    }
-                                } else {
-                                    field.set(null, null);
-                                    if (log.isDebugEnabled()) {
-                                        log.debug("Set field " + field.getName()
-                                                + " to null in class " + clazz.getName());
-                                    }
-                                }
-                            } catch (Throwable t) {
-                                ExceptionUtils.handleThrowable(t);
-                                if (log.isDebugEnabled()) {
-                                    log.debug("Could not set field " + field.getName()
-                                            + " to null in class " + clazz.getName(), t);
-                                }
-                            }
-                        }
-                    }
-                } catch (Throwable t) {
-                    ExceptionUtils.handleThrowable(t);
-                    if (log.isDebugEnabled()) {
-                        log.debug("Could not clean fields for class " + clazz.getName(), t);
-                    }
-                }
-            }
-        }
-
-    }
-
-
-    private void nullInstance(Object instance) {
-        if (instance == null) {
-            return;
-        }
-        Field[] fields = instance.getClass().getDeclaredFields();
-        for (int i = 0; i < fields.length; i++) {
-            Field field = fields[i];
-            int mods = field.getModifiers();
-            if (field.getType().isPrimitive()
-                    || (field.getName().indexOf('$') != -1)) {
-                continue;
-            }
-            try {
-                field.setAccessible(true);
-                if (Modifier.isStatic(mods) && Modifier.isFinal(mods)) {
-                    // Doing something recursively is too risky
-                    continue;
-                }
-                Object value = field.get(instance);
-                if (null != value) {
-                    Class<? extends Object> valueClass = value.getClass();
-                    if (!loadedByThisOrChild(valueClass)) {
-                        if (log.isDebugEnabled()) {
-                            log.debug("Not setting field " + field.getName() +
-                                    " to null in object of class " +
-                                    instance.getClass().getName() +
-                                    " because the referenced object was of type " +
-                                    valueClass.getName() +
-                                    " which was not loaded by this web application class loader.");
-                        }
-                    } else {
-                        field.set(instance, null);
-                        if (log.isDebugEnabled()) {
-                            log.debug("Set field " + field.getName()
-                                    + " to null in class " + instance.getClass().getName());
-                        }
-                    }
-                }
-            } catch (Throwable t) {
-                ExceptionUtils.handleThrowable(t);
-                if (log.isDebugEnabled()) {
-                    log.debug("Could not set field " + field.getName()
-                            + " to null in object instance of class "
-                            + instance.getClass().getName(), t);
-                }
-            }
-        }
-    }
-
 
     @SuppressWarnings("deprecation") // thread.stop()
     private void clearReferencesThreads() {

Modified: tomcat/trunk/test/org/apache/catalina/loader/TestWebappClassLoaderWeaving.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/loader/TestWebappClassLoaderWeaving.java?rev=1744713&r1=1744712&r2=1744713&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/loader/TestWebappClassLoaderWeaving.java (original)
+++ tomcat/trunk/test/org/apache/catalina/loader/TestWebappClassLoaderWeaving.java Fri May 20 11:18:55 2016
@@ -239,7 +239,6 @@ public class TestWebappClassLoaderWeavin
 
     }
 
-    @SuppressWarnings("deprecation")
     @Test
     public void testCopiedClassLoaderExcludesResourcesAndTransformers() throws Exception {
 
@@ -266,9 +265,6 @@ public class TestWebappClassLoaderWeavin
         assertEquals("getClearReferencesLogFactoryRelease did not match.",
                 Boolean.valueOf(this.loader.getClearReferencesLogFactoryRelease()),
                 Boolean.valueOf(copiedLoader.getClearReferencesLogFactoryRelease()));
-        assertEquals("getClearReferencesStatic did not match.",
-                Boolean.valueOf(this.loader.getClearReferencesStatic()),
-                Boolean.valueOf(copiedLoader.getClearReferencesStatic()));
         assertEquals("getClearReferencesStopThreads did not match.",
                 Boolean.valueOf(this.loader.getClearReferencesStopThreads()),
                 Boolean.valueOf(copiedLoader.getClearReferencesStopThreads()));

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1744713&r1=1744712&r2=1744713&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Fri May 20 11:18:55 2016
@@ -59,6 +59,13 @@
         Ensure NPE will not be thrown during deployment when scanning jar files
         without MANIFEST.MF file. (violetagg)
       </fix>
+      <scode>
+        Remove the <code>clearReferencesStatic</code> option from
+        <code>StandardContext</code>. It was known to cause problems with some
+        libraries (such as log4j) and was only linked to suspected memory leaks
+        rather than known memory leaks. It had been disabled by default with no
+        increase in the reports of memory leaks for some time. (markt)
+      </scode>
     </changelog>
   </subsection>
   <subsection name="Coyote">

Modified: tomcat/trunk/webapps/docs/config/context.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/context.xml?rev=1744713&r1=1744712&r2=1744713&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/context.xml (original)
+++ tomcat/trunk/webapps/docs/config/context.xml Fri May 20 11:18:55 2016
@@ -698,19 +698,6 @@
         If not specified, the default value of <code>true</code> will be used.</p>
       </attribute>
 
-      <attribute name="clearReferencesStatic" required="false">
-        <p>If <code>true</code>, Tomcat attempts to null out any static or final
-        fields from loaded classes when a web application is stopped as a work
-        around for apparent garbage collection bugs and application coding
-        errors. There have been some issues reported with log4j when this
-        is <code>true</code>. Applications without memory leaks using recent
-        JVMs should operate correctly with this attribute set to
-        <code>false</code>. If not specified, the default value of
-        <code>false</code> will be used.</p>
-        <p>This attribute has been deprecated and will be removed in Tomcat
-        8.5.</p>
-      </attribute>
-
       <attribute name="clearReferencesStopThreads" required="false">
         <p>If <code>true</code>, Tomcat attempts to terminate threads that have
         been started by the web application. Stopping threads is performed via



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org