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-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to