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

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

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

    Synchronize 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 bc0ca4f1a9..51950cb768 100644
--- a/java/org/apache/catalina/core/StandardHost.java
+++ b/java/org/apache/catalina/core/StandardHost.java
@@ -170,6 +170,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
@@ -691,8 +697,10 @@ public class StandardHost extends ContainerBase implements 
Host {
             if (event.getType().equals(AFTER_START_EVENT)) {
                 if (event.getSource() instanceof Context) {
                     Context context = ((Context) event.getSource());
-                    childClassLoaders.put(context.getLoader().getClassLoader(),
-                            context.getServletContext().getContextPath());
+                    synchronized (childClassLoadersLock) {
+                        
childClassLoaders.put(context.getLoader().getClassLoader(),
+                                context.getServletContext().getContextPath());
+                    }
                 }
             }
         }
@@ -712,7 +720,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