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 2018/03/13 23:24:02 UTC

svn commit: r1826688 - in /tomcat/trunk: bin/ java/org/apache/catalina/core/ java/org/apache/catalina/loader/ res/ webapps/docs/ webapps/docs/config/

Author: markt
Date: Tue Mar 13 23:24:01 2018
New Revision: 1826688

URL: http://svn.apache.org/viewvc?rev=1826688&view=rev
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=51195
Avoid a false positive report of a web application memory leak by clearing ObjectStreamClass$Caches of classes loaded by the web application when the web application is stopped.

Modified:
    tomcat/trunk/bin/catalina.bat
    tomcat/trunk/bin/catalina.sh
    tomcat/trunk/bin/service.bat
    tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
    tomcat/trunk/java/org/apache/catalina/loader/LocalStrings.properties
    tomcat/trunk/java/org/apache/catalina/loader/WebappClassLoaderBase.java
    tomcat/trunk/res/tomcat.nsi
    tomcat/trunk/webapps/docs/changelog.xml
    tomcat/trunk/webapps/docs/config/context.xml
    tomcat/trunk/webapps/docs/setup.xml

Modified: tomcat/trunk/bin/catalina.bat
URL: http://svn.apache.org/viewvc/tomcat/trunk/bin/catalina.bat?rev=1826688&r1=1826687&r2=1826688&view=diff
==============================================================================
--- tomcat/trunk/bin/catalina.bat (original)
+++ tomcat/trunk/bin/catalina.bat Tue Mar 13 23:24:01 2018
@@ -224,6 +224,7 @@ set LOGGING_MANAGER=-Djava.util.logging.
 
 rem Configure JAVA 9 specific start-up parameters
 set "JDK_JAVA_OPTIONS=%JDK_JAVA_OPTIONS% --add-opens=java.base/java.lang=ALL-UNNAMED"
+set "JDK_JAVA_OPTIONS=%JDK_JAVA_OPTIONS% --add-opens=java.base/java.io=ALL-UNNAMED"
 set "JDK_JAVA_OPTIONS=%JDK_JAVA_OPTIONS% --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"
 
 rem Java 9 no longer supports the java.endorsed.dirs

Modified: tomcat/trunk/bin/catalina.sh
URL: http://svn.apache.org/viewvc/tomcat/trunk/bin/catalina.sh?rev=1826688&r1=1826687&r2=1826688&view=diff
==============================================================================
--- tomcat/trunk/bin/catalina.sh (original)
+++ tomcat/trunk/bin/catalina.sh Tue Mar 13 23:24:01 2018
@@ -302,6 +302,7 @@ fi
 
 # Add the JAVA 9 specific start-up parameters required by Tomcat
 JDK_JAVA_OPTIONS="$JDK_JAVA_OPTIONS --add-opens=java.base/java.lang=ALL-UNNAMED"
+JDK_JAVA_OPTIONS="$JDK_JAVA_OPTIONS --add-opens=java.base/java.io=ALL-UNNAMED"
 JDK_JAVA_OPTIONS="$JDK_JAVA_OPTIONS --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"
 export JDK_JAVA_OPTIONS
 

Modified: tomcat/trunk/bin/service.bat
URL: http://svn.apache.org/viewvc/tomcat/trunk/bin/service.bat?rev=1826688&r1=1826687&r2=1826688&view=diff
==============================================================================
--- tomcat/trunk/bin/service.bat (original)
+++ tomcat/trunk/bin/service.bat Tue Mar 13 23:24:01 2018
@@ -184,7 +184,7 @@ if "%JvmMx%" == "" set JvmMx=256
     --StartParams start ^
     --StopParams stop ^
     --JvmOptions "-Dcatalina.home=%CATALINA_HOME%;-Dcatalina.base=%CATALINA_BASE%;-D%ENDORSED_PROP%=%CATALINA_HOME%\endorsed;-Djava.io.tmpdir=%CATALINA_BASE%\temp;-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager;-Djava.util.logging.config.file=%CATALINA_BASE%\conf\logging.properties;%JvmArgs%" ^
-    --JvmOptions9 "--add-opens=java.base/java.lang=ALL-UNNAMED#--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED" ^
+    --JvmOptions9 "--add-opens=java.base/java.lang=ALL-UNNAMED#--add-opens=java.base/java.io=ALL-UNNAMED#--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED" ^
     --Startup "%SERVICE_STARTUP_MODE%" ^
     --JvmMs "%JvmMs%" ^
     --JvmMx "%JvmMx%"

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=1826688&r1=1826687&r2=1826688&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Tue Mar 13 23:24:01 2018
@@ -737,6 +737,12 @@ public class StandardContext extends Con
     private boolean renewThreadsWhenStoppingContext = true;
 
     /**
+     * Should Tomcat attempt to clear references to classes loaded by the web
+     * application class loader from the ObjectStreamClass caches?
+     */
+    private boolean clearReferencesObjectStreamClassCaches = true;
+
+    /**
      * Should the effective web.xml be logged when the context starts?
      */
     private boolean logEffectiveWebXml = false;
@@ -2652,6 +2658,23 @@ public class StandardContext extends Con
                 this.renewThreadsWhenStoppingContext);
     }
 
+
+    public boolean getClearReferencesObjectStreamClassCaches() {
+        return clearReferencesObjectStreamClassCaches;
+    }
+
+
+    public void setClearReferencesObjectStreamClassCaches(
+            boolean clearReferencesObjectStreamClassCaches) {
+        boolean oldClearReferencesObjectStreamClassCaches =
+                this.clearReferencesObjectStreamClassCaches;
+        this.clearReferencesObjectStreamClassCaches = clearReferencesObjectStreamClassCaches;
+        support.firePropertyChange("clearReferencesObjectStreamClassCaches",
+                oldClearReferencesObjectStreamClassCaches,
+                this.clearReferencesObjectStreamClassCaches);
+    }
+
+
     public Boolean getFailCtxIfServletStartFails() {
         return failCtxIfServletStartFails;
     }
@@ -4901,6 +4924,8 @@ public class StandardContext extends Con
                         getClearReferencesStopTimerThreads());
                 setClassLoaderProperty("clearReferencesHttpClientKeepAliveThread",
                         getClearReferencesHttpClientKeepAliveThread());
+                setClassLoaderProperty("clearReferencesObjectStreamClassCaches",
+                        getClearReferencesObjectStreamClassCaches());
 
                 // By calling unbindThread and bindThread in a row, we setup the
                 // current Thread CCL to be the webapp classloader

Modified: tomcat/trunk/java/org/apache/catalina/loader/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/loader/LocalStrings.properties?rev=1826688&r1=1826687&r2=1826688&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/loader/LocalStrings.properties (original)
+++ tomcat/trunk/java/org/apache/catalina/loader/LocalStrings.properties Tue Mar 13 23:24:01 2018
@@ -22,6 +22,7 @@ webappClassLoader.jdbcRemoveFailed=JDBC
 webappClassLoader.stopped=Illegal access: this web application instance has been stopped already. Could not load [{0}]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
 webappClassLoader.readError=Resource read error: Could not load [{0}].
 webappClassLoader.clearJdbc=The web application [{0}] registered the JDBC driver [{1}] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
+webappClassLoader.clearObjectStreamClassCachesFail=Failed to clear soft references from ObjectStreamClass$Caches for web application [{0}]
 webappClassLoader.clearReferencesResourceBundlesCount=Removed [{0}] ResourceBundle references from the cache for web application [{1}]
 webappClassLoader.clearReferencesResourceBundlesFail=Failed to clear ResourceBundle references for web application [{0}]
 webappClassLoader.clearRmi=Found RMI Target with stub class class [{0}] and value [{1}]. This RMI Target has been forcibly removed to prevent a memory leak.

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=1826688&r1=1826687&r2=1826688&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/loader/WebappClassLoaderBase.java (original)
+++ tomcat/trunk/java/org/apache/catalina/loader/WebappClassLoaderBase.java Tue Mar 13 23:24:01 2018
@@ -362,6 +362,12 @@ public abstract class WebappClassLoaderB
     private boolean clearReferencesHttpClientKeepAliveThread = true;
 
     /**
+     * Should Tomcat attempt to clear references to classes loaded by this class
+     * loader from the ObjectStreamClass caches?
+     */
+    private boolean clearReferencesObjectStreamClassCaches = true;
+
+    /**
      * Holds the class file transformers decorating this class loader. The
      * CopyOnWriteArrayList is thread safe. It is expensive on writes, but
      * those should be rare. It is very fast on reads, since synchronization
@@ -596,6 +602,17 @@ public abstract class WebappClassLoaderB
     }
 
 
+    public boolean getClearReferencesObjectStreamClassCaches() {
+        return clearReferencesObjectStreamClassCaches;
+    }
+
+
+    public void setClearReferencesObjectStreamClassCaches(
+            boolean clearReferencesObjectStreamClassCaches) {
+        this.clearReferencesObjectStreamClassCaches = clearReferencesObjectStreamClassCaches;
+    }
+
+
     // ------------------------------------------------------- Reloader Methods
 
     /**
@@ -1513,6 +1530,11 @@ public abstract class WebappClassLoaderB
         // Stop any threads the web application started
         clearReferencesThreads();
 
+        // Clear any references retained in the serialization caches
+        if (clearReferencesObjectStreamClassCaches) {
+            clearReferencesObjectStreamClassCaches();
+        }
+
         // Check for leaks triggered by ThreadLocals loaded by this class loader
         checkThreadLocalsForLeaks();
 
@@ -2132,6 +2154,36 @@ public abstract class WebappClassLoaderB
             }
         }
     }
+
+
+    private void clearReferencesObjectStreamClassCaches() {
+        try {
+            Class<?> clazz = Class.forName("java.io.ObjectStreamClass$Caches");
+            clearCache(clazz, "localDescs");
+            clearCache(clazz, "reflectors");
+        } catch (ReflectiveOperationException | SecurityException | ClassCastException e) {
+            log.warn(sm.getString(
+                    "webappClassLoader.clearObjectStreamClassCachesFail", getContextName()), e);
+        }
+    }
+
+
+    private void clearCache(Class<?> target, String mapName)
+            throws ReflectiveOperationException, SecurityException, ClassCastException {
+        Field f = target.getDeclaredField(mapName);
+        f.setAccessible(true);
+        Map<?,?> map = (Map<?,?>) f.get(null);
+        Iterator<?> keys = map.keySet().iterator();
+        while (keys.hasNext()) {
+            Object key = keys.next();
+            if (key instanceof Reference) {
+                Object clazz = ((Reference<?>) key).get();
+                if (loadedByThisOrChild(clazz)) {
+                    keys.remove();
+                }
+            }
+        }
+    }
 
 
     /**

Modified: tomcat/trunk/res/tomcat.nsi
URL: http://svn.apache.org/viewvc/tomcat/trunk/res/tomcat.nsi?rev=1826688&r1=1826687&r2=1826688&view=diff
==============================================================================
--- tomcat/trunk/res/tomcat.nsi (original)
+++ tomcat/trunk/res/tomcat.nsi Tue Mar 13 23:24:01 2018
@@ -322,7 +322,7 @@ Section -post
     FileWrite $ServiceInstallLog "$\r$\n"
     FileWrite $ServiceInstallLog '"$INSTDIR\bin\$TomcatServiceFileName" //US//$TomcatServiceName --JvmOptions "-Dcatalina.home=$INSTDIR#-Dcatalina.base=$INSTDIR#-Djava.io.tmpdir=$INSTDIR\temp#-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager#-Djava.util.logging.config.file=$INSTDIR\conf\logging.properties"'
     FileWrite $ServiceInstallLog "$\r$\n"
-    FileWrite $ServiceInstallLog '"$INSTDIR\bin\$TomcatServiceFileName" //US//$TomcatServiceName --JvmOptions9 "--add-opens=java.base/java.lang=ALL-UNNAMED#--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"'
+    FileWrite $ServiceInstallLog '"$INSTDIR\bin\$TomcatServiceFileName" //US//$TomcatServiceName --JvmOptions9 "--add-opens=java.base/java.lang=ALL-UNNAMED#--add-opens=java.base/java.io=ALL-UNNAMED#--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"'
     FileWrite $ServiceInstallLog "$\r$\n"
     FileWrite $ServiceInstallLog '"$INSTDIR\bin\$TomcatServiceFileName" //US//$TomcatServiceName --StdOutput auto --StdError auto --JvmMs 128 --JvmMx 256'
     FileWrite $ServiceInstallLog "$\r$\n"
@@ -332,7 +332,7 @@ Section -post
   DetailPrint "Configuring $TomcatServiceName service"
   nsExec::ExecToLog '"$INSTDIR\bin\$TomcatServiceFileName" //US//$TomcatServiceName --Classpath "$INSTDIR\bin\bootstrap.jar;$INSTDIR\bin\tomcat-juli.jar" --StartClass org.apache.catalina.startup.Bootstrap --StopClass org.apache.catalina.startup.Bootstrap --StartParams start --StopParams stop  --StartMode jvm --StopMode jvm'
   nsExec::ExecToLog '"$INSTDIR\bin\$TomcatServiceFileName" //US//$TomcatServiceName --JvmOptions "-Dcatalina.home=$INSTDIR#-Dcatalina.base=$INSTDIR#-Djava.io.tmpdir=$INSTDIR\temp#-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager#-Djava.util.logging.config.file=$INSTDIR\conf\logging.properties"'
-  nsExec::ExecToLog '"$INSTDIR\bin\$TomcatServiceFileName" //US//$TomcatServiceName --JvmOptions9 "--add-opens=java.base/java.lang=ALL-UNNAMED#--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"'
+  nsExec::ExecToLog '"$INSTDIR\bin\$TomcatServiceFileName" //US//$TomcatServiceName --JvmOptions9 "--add-opens=java.base/java.lang=ALL-UNNAMED#--add-opens=java.base/java.io=ALL-UNNAMED#--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"'
   nsExec::ExecToLog '"$INSTDIR\bin\$TomcatServiceFileName" //US//$TomcatServiceName --StdOutput auto --StdError auto --JvmMs 128 --JvmMx 256'
 
   ${If} $TomcatShortcutAllUsers == "1"

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1826688&r1=1826687&r2=1826688&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Tue Mar 13 23:24:01 2018
@@ -48,6 +48,12 @@
   <subsection name="Catalina">
     <changelog>
       <fix>
+        <bug>51195</bug>: Avoid a false positive report of a web application
+        memory leak by clearing <code>ObjectStreamClass$Caches</code> of classes
+        loaded by the web application when the web application is stopped.
+        (markt)
+      </fix>
+      <fix>
         Ensure the MBean names for the <code>SSLHostConfig</code> and
         <code>SSLHostConfigCertificate</code> are correctly formed when the
         <code>Connector</code> is bound to a specific IP address. (markt)

Modified: tomcat/trunk/webapps/docs/config/context.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/context.xml?rev=1826688&r1=1826687&r2=1826688&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/context.xml (original)
+++ tomcat/trunk/webapps/docs/config/context.xml Tue Mar 13 23:24:01 2018
@@ -711,6 +711,18 @@
         not specified, the default value of <code>true</code> will be used.</p>
       </attribute>
 
+      <attribute name="clearReferencesObjectStreamClassCaches" required="false">
+        <p>If <code>true</code>, when the web application is stopped Tomcat
+        looks for <code>SoftReference</code>s to classes loaded by the web
+        application in the <code>ObjectStreamClass</code> class used for
+        serialization and clears any <code>SoftReference</code>s it finds. This
+        feature uses reflection to identify the <code>SoftReference</code>s and
+        therefore requires that the command line option
+        <code>-XaddExports:java.base/java.io=ALL-UNNAMED</code> is set
+        when running on Java 9 and above. If not specified, the default value of
+        <code>true</code> will be used.</p>
+      </attribute>
+
       <attribute name="clearReferencesRmiTargets" required="false">
         <p>If <code>true</code>, Tomcat looks for memory leaks associated with
         RMI Targets and clears any it finds. This feature uses reflection to

Modified: tomcat/trunk/webapps/docs/setup.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/setup.xml?rev=1826688&r1=1826687&r2=1826688&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/setup.xml (original)
+++ tomcat/trunk/webapps/docs/setup.xml Tue Mar 13 23:24:01 2018
@@ -157,6 +157,7 @@ cd $CATALINA_HOME
     following when starting jsvc to avoid warnings on shutdown.</p>
 <source>...
 --add-opens=java.base/java.lang=ALL-UNNAMED \
+--add-opens=java.base/java.io=ALL-UNNAMED \
 --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED \
 ...
 </source>



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