This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-jxpath.git
commit 0ebb4a3a35284ed77874467e809c67ab227347ce Author: Gary Gregory <[email protected]> AuthorDate: Sun Nov 16 10:25:17 2025 -0500 Refactor JXPathIntrospector internal static maps to use concurrent classes instead of synchronization --- src/changes/changes.xml | 1 + .../apache/commons/jxpath/JXPathIntrospector.java | 40 ++++++++-------------- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 80da5642..8d2fc7d0 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,7 @@ The <action> type attribute can be add,update,fix,remove. <!-- FIX --> <action type="fix" dev="ggregory" due-to="Gary Gregory">POM assembly:single does not generate binary convenience files (tar/zip).</action> <action type="fix" dev="ggregory" due-to="Dima1224, Gary Gregory">Make dynamicPropertyHandlerMap in ValueUtils thread-safe #251.</action> + <action type="fix" dev="ggregory" due-to="Gary Gregory">Refactor JXPathIntrospector internal static maps to use concurrent classes instead of synchronization.</action> <!-- ADD --> <!-- UPDATE --> <action type="update" dev="ggregory" due-to="Gary Gregory, Dependabot">Bump org.apache.commons:commons-parent from 81 to 91 #239, #262, #265.</action> diff --git a/src/main/java/org/apache/commons/jxpath/JXPathIntrospector.java b/src/main/java/org/apache/commons/jxpath/JXPathIntrospector.java index b1ffac1e..c9a65683 100644 --- a/src/main/java/org/apache/commons/jxpath/JXPathIntrospector.java +++ b/src/main/java/org/apache/commons/jxpath/JXPathIntrospector.java @@ -17,10 +17,10 @@ package org.apache.commons.jxpath; -import java.util.Collections; import java.util.Date; -import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import org.apache.commons.jxpath.util.ClassLoaderUtil; @@ -29,8 +29,8 @@ import org.apache.commons.jxpath.util.ClassLoaderUtil; */ public class JXPathIntrospector { - private static Map<Class, JXPathBeanInfo> byClass = Collections.synchronizedMap(new HashMap<>()); - private static Map<Class, JXPathBeanInfo> byInterface = Collections.synchronizedMap(new HashMap<>()); + private static ConcurrentMap<Class, JXPathBeanInfo> byClass = new ConcurrentHashMap<>(); + private static ConcurrentMap<Class, JXPathBeanInfo> byInterface = new ConcurrentHashMap<>(); static { registerAtomicClass(Class.class); registerAtomicClass(Boolean.TYPE); @@ -130,20 +130,16 @@ public class JXPathIntrospector { * @return JXPathBeanInfo */ public static JXPathBeanInfo getBeanInfo(final Class beanClass) { - JXPathBeanInfo beanInfo = byClass.get(beanClass); - if (beanInfo == null) { - beanInfo = findDynamicBeanInfo(beanClass); - if (beanInfo == null) { - beanInfo = findInformant(beanClass); - if (beanInfo == null) { - beanInfo = new JXPathBasicBeanInfo(beanClass); + return byClass.computeIfAbsent(beanClass, k -> { + JXPathBeanInfo value = findDynamicBeanInfo(beanClass); + if (value == null) { + value = findInformant(beanClass); + if (value == null) { + value = new JXPathBasicBeanInfo(beanClass); } } - synchronized (byClass) { - byClass.put(beanClass, beanInfo); - } - } - return beanInfo; + return value; + }); } /** @@ -175,9 +171,7 @@ public class JXPathIntrospector { * @param beanClass to register */ public static void registerAtomicClass(final Class beanClass) { - synchronized (byClass) { - byClass.put(beanClass, new JXPathBasicBeanInfo(beanClass, true)); - } + byClass.computeIfAbsent(beanClass, k -> new JXPathBasicBeanInfo(beanClass, true)); } /** @@ -190,13 +184,9 @@ public class JXPathIntrospector { public static void registerDynamicClass(final Class beanClass, final Class dynamicPropertyHandlerClass) { final JXPathBasicBeanInfo bi = new JXPathBasicBeanInfo(beanClass, dynamicPropertyHandlerClass); if (beanClass.isInterface()) { - synchronized (byInterface) { - byInterface.put(beanClass, bi); - } + byInterface.put(beanClass, bi); } else { - synchronized (byClass) { - byClass.put(beanClass, bi); - } + byClass.put(beanClass, bi); } }
