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 fb00dbdcca139a83279ca29c92d479dcec4a1c5d Author: opencode <[email protected]> AuthorDate: Thu Oct 15 10:55:01 2026 +0200 Synchronize the registry metadata maps The descriptors, descriptorsByClass and searchedPaths maps were plain HashMaps mutated by addManagedBean() and loadDescriptors() and read by findManagedBean(), registerComponent() and findDescriptor() with no synchronization, while registerComponent() is invoked concurrently during parallel web application deployment and from worker threads on first use of an upgrade protocol. Concurrent access could lose updates or transiently corrupt the map state, and stop() additionally reassigned the three non-volatile fields while readers were active. Make the three maps final ConcurrentHashMaps and have stop() clear them rather than reassign them. Record the searched package atomically with putIfAbsent so concurrent first loads of the same package can not both parse the descriptor file, and skip the name-keyed entry when a ManagedBean has no name (permitted by the DTD) since ConcurrentHashMap does not allow null keys, preserving the previous behavior for such descriptors. --- java/org/apache/tomcat/util/modeler/Registry.java | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/java/org/apache/tomcat/util/modeler/Registry.java b/java/org/apache/tomcat/util/modeler/Registry.java index 47d5746c1b..a369b1eadf 100644 --- a/java/org/apache/tomcat/util/modeler/Registry.java +++ b/java/org/apache/tomcat/util/modeler/Registry.java @@ -21,10 +21,10 @@ import java.io.FileInputStream; import java.io.InputStream; import java.lang.management.ManagementFactory; import java.net.URL; -import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import javax.management.DynamicMBean; import javax.management.InstanceNotFoundException; @@ -72,15 +72,15 @@ public class Registry implements RegistryMBean, MBeanRegistration { /** * The set of ManagedBean instances for the beans this registry knows about, keyed by name. */ - private Map<String,ManagedBean> descriptors = new HashMap<>(); + private final Map<String,ManagedBean> descriptors = new ConcurrentHashMap<>(); /** * List of managed beans, keyed by class name */ - private Map<String,ManagedBean> descriptorsByClass = new HashMap<>(); + private final Map<String,ManagedBean> descriptorsByClass = new ConcurrentHashMap<>(); // map to avoid duplicated searching or loading descriptors - private Map<String,URL> searchedPaths = new HashMap<>(); + private final Map<String,URL> searchedPaths = new ConcurrentHashMap<>(); private Object guard; @@ -168,9 +168,9 @@ public class Registry implements RegistryMBean, MBeanRegistration { */ @Override public void stop() { - descriptorsByClass = new HashMap<>(); - descriptors = new HashMap<>(); - searchedPaths = new HashMap<>(); + descriptorsByClass.clear(); + descriptors.clear(); + searchedPaths.clear(); } @@ -297,7 +297,9 @@ public class Registry implements RegistryMBean, MBeanRegistration { */ public void addManagedBean(ManagedBean bean) { // XXX Use group + name - descriptors.put(bean.getName(), bean); + if (bean.getName() != null) { + descriptors.put(bean.getName(), bean); + } if (bean.getType() != null) { descriptorsByClass.put(bean.getType(), bean); } @@ -682,7 +684,10 @@ public class Registry implements RegistryMBean, MBeanRegistration { if (log.isTraceEnabled()) { log.trace("Found " + dURL); } - searchedPaths.put(packageName, dURL); + if (searchedPaths.putIfAbsent(packageName, dURL) != null) { + // Another thread claimed this package first and is loading it + return; + } try { load("MbeansDescriptorsDigesterSource", dURL, null); } catch (Exception e) { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
