This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit be639f85e902a70990d3e4880dbc04e800a5892d
Author: opencode <[email protected]>
AuthorDate: Wed Sep 30 13:27:25 2026 +0200

    Synchronise access to the StandardHost childClassLoaders map which is 
written by context start threads and read by findReloadedContextMemoryLeaks() 
from Manager/JMX threads, preventing concurrent modification of the underlying 
WeakHashMap during iteration
---
 java/org/apache/catalina/core/StandardHost.java | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/java/org/apache/catalina/core/StandardHost.java 
b/java/org/apache/catalina/core/StandardHost.java
index 86fff7b482..06f215c58e 100644
--- a/java/org/apache/catalina/core/StandardHost.java
+++ b/java/org/apache/catalina/core/StandardHost.java
@@ -169,6 +169,12 @@ public class StandardHost extends ContainerBase implements 
Host {
      */
     private final Map<ClassLoader,String> childClassLoaders = new 
WeakHashMap<>();
 
+    /**
+     * Lock used to synchronise access to {@link #childClassLoaders} which is 
written when child contexts start and
+     * read when memory leaks are checked.
+     */
+    private final Object childClassLoadersLock = new Object();
+
 
     /**
      * Any file or directory in {@link #appBase} that this pattern matches 
will be ignored by the automatic deployment
@@ -688,8 +694,10 @@ public class StandardHost extends ContainerBase implements 
Host {
         public void lifecycleEvent(LifecycleEvent event) {
             if (event.getType().equals(AFTER_START_EVENT)) {
                 if (event.getSource() instanceof Context context) {
-                    childClassLoaders.put(context.getLoader().getClassLoader(),
-                            context.getServletContext().getContextPath());
+                    synchronized (childClassLoadersLock) {
+                        
childClassLoaders.put(context.getLoader().getClassLoader(),
+                                context.getServletContext().getContextPath());
+                    }
                 }
             }
         }
@@ -709,7 +717,12 @@ public class StandardHost extends ContainerBase implements 
Host {
 
         List<String> result = new ArrayList<>();
 
-        for (Map.Entry<ClassLoader,String> entry : 
childClassLoaders.entrySet()) {
+        List<Map.Entry<ClassLoader,String>> entries;
+        synchronized (childClassLoadersLock) {
+            entries = new ArrayList<>(childClassLoaders.entrySet());
+        }
+
+        for (Map.Entry<ClassLoader,String> entry : entries) {
             ClassLoader cl = entry.getKey();
             if (cl instanceof WebappClassLoaderBase) {
                 if (!((WebappClassLoaderBase) cl).getState().isAvailable()) {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to