Skip to content

Commit 49e5c5e

Browse files
authored
Replace ConcurrentHashMap#computeIfAbsent to avoid potential deadlock (#15456)
1 parent 4f5ca88 commit 49e5c5e

36 files changed

Lines changed: 191 additions & 152 deletions

File tree

dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.apache.dubbo.common.utils.ClassLoaderResourceLoader;
3434
import org.apache.dubbo.common.utils.ClassUtils;
3535
import org.apache.dubbo.common.utils.CollectionUtils;
36+
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
3637
import org.apache.dubbo.common.utils.ConcurrentHashSet;
3738
import org.apache.dubbo.common.utils.ConfigUtils;
3839
import org.apache.dubbo.common.utils.Holder;
@@ -141,7 +142,7 @@ public class ExtensionLoader<T> {
141142

142143
private static final Map<String, String> specialSPILoadingStrategyMap = getSpecialSPILoadingStrategyMap();
143144

144-
private static SoftReference<Map<java.net.URL, List<String>>> urlListMapCache =
145+
private static SoftReference<ConcurrentHashMap<java.net.URL, List<String>>> urlListMapCache =
145146
new SoftReference<>(new ConcurrentHashMap<>());
146147

147148
private static final List<String> ignoredInjectMethodsDesc = getIgnoredInjectMethodsDesc();
@@ -1189,7 +1190,7 @@ && isIncluded(clazz, includedPackages)
11891190
}
11901191

11911192
private List<String> getResourceContent(java.net.URL resourceURL) throws IOException {
1192-
Map<java.net.URL, List<String>> urlListMap = urlListMapCache.get();
1193+
ConcurrentHashMap<java.net.URL, List<String>> urlListMap = urlListMapCache.get();
11931194
if (urlListMap == null) {
11941195
synchronized (ExtensionLoader.class) {
11951196
if ((urlListMap = urlListMapCache.get()) == null) {
@@ -1199,7 +1200,7 @@ private List<String> getResourceContent(java.net.URL resourceURL) throws IOExcep
11991200
}
12001201
}
12011202

1202-
List<String> contentList = urlListMap.computeIfAbsent(resourceURL, key -> {
1203+
List<String> contentList = ConcurrentHashMapUtils.computeIfAbsent(urlListMap, resourceURL, key -> {
12031204
List<String> newContentList = new ArrayList<>();
12041205

12051206
try (BufferedReader reader =

dubbo-common/src/main/java/org/apache/dubbo/common/serialization/ClassHolder.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,17 @@
1616
*/
1717
package org.apache.dubbo.common.serialization;
1818

19+
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
1920
import org.apache.dubbo.common.utils.ConcurrentHashSet;
2021

21-
import java.util.Map;
2222
import java.util.Set;
2323
import java.util.concurrent.ConcurrentHashMap;
2424

2525
public class ClassHolder {
26-
private final Map<String, Set<Class<?>>> classCache = new ConcurrentHashMap<>();
26+
private final ConcurrentHashMap<String, Set<Class<?>>> classCache = new ConcurrentHashMap<>();
2727

2828
public void storeClass(Class<?> clazz) {
29-
classCache
30-
.computeIfAbsent(clazz.getName(), k -> new ConcurrentHashSet<>())
29+
ConcurrentHashMapUtils.computeIfAbsent(classCache, clazz.getName(), k -> new ConcurrentHashSet<>())
3130
.add(clazz);
3231
}
3332

dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ private static Field getAndCacheField(Class<?> cls, String fieldName) {
763763

764764
if (result != null) {
765765
ConcurrentMap<String, Field> fields =
766-
CLASS_FIELD_CACHE.computeIfAbsent(cls, k -> new ConcurrentHashMap<>());
766+
ConcurrentHashMapUtils.computeIfAbsent(CLASS_FIELD_CACHE, cls, k -> new ConcurrentHashMap<>());
767767
fields.putIfAbsent(fieldName, result);
768768
}
769769
return result;

dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,8 @@ public static <T> T computeServiceAttribute(URL url, String key, Function<URL, T
696696
return Optional.ofNullable(url.getServiceModel())
697697
.map(ServiceModel::getServiceMetadata)
698698
.map(ServiceMetadata::getAttributeMap)
699-
.map(stringObjectMap -> (T) stringObjectMap.computeIfAbsent(key, k -> fn.apply(url)))
699+
.map(stringObjectMap ->
700+
(T) ConcurrentHashMapUtils.computeIfAbsent(stringObjectMap, key, k -> fn.apply(url)))
700701
.orElse(null);
701702
}
702703
}

dubbo-common/src/main/java/org/apache/dubbo/config/context/AbstractConfigManager.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
2626
import org.apache.dubbo.common.logger.LoggerFactory;
2727
import org.apache.dubbo.common.utils.CollectionUtils;
28+
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
2829
import org.apache.dubbo.common.utils.ConcurrentHashSet;
2930
import org.apache.dubbo.common.utils.ReflectUtils;
3031
import org.apache.dubbo.common.utils.StringUtils;
@@ -73,9 +74,9 @@ public abstract class AbstractConfigManager extends LifecycleAdapter {
7374
LoggerFactory.getErrorTypeAwareLogger(AbstractConfigManager.class);
7475
private static final Set<Class<? extends AbstractConfig>> uniqueConfigTypes = new ConcurrentHashSet<>();
7576

76-
final Map<String, Map<String, AbstractConfig>> configsCache = new ConcurrentHashMap<>();
77+
final ConcurrentHashMap<String, Map<String, AbstractConfig>> configsCache = new ConcurrentHashMap<>();
7778

78-
private final Map<String, AtomicInteger> configIdIndexes = new ConcurrentHashMap<>();
79+
private final ConcurrentHashMap<String, AtomicInteger> configIdIndexes = new ConcurrentHashMap<>();
7980

8081
protected Set<AbstractConfig> duplicatedConfigs = new ConcurrentHashSet<>();
8182

@@ -163,8 +164,8 @@ public final <T extends AbstractConfig> T addConfig(AbstractConfig config) {
163164

164165
Class<? extends AbstractConfig> targetConfigType = getTargetConfigType(config.getClass());
165166

166-
Map<String, AbstractConfig> configsMap =
167-
configsCache.computeIfAbsent(getTagName(targetConfigType), type -> new ConcurrentHashMap<>());
167+
Map<String, AbstractConfig> configsMap = ConcurrentHashMapUtils.computeIfAbsent(
168+
configsCache, getTagName(targetConfigType), type -> new ConcurrentHashMap<>());
168169

169170
// fast check duplicated equivalent config before write lock
170171
if (!(config instanceof ReferenceConfigBase || config instanceof ServiceConfigBase)) {
@@ -408,8 +409,7 @@ protected boolean isEquals(AbstractConfig oldOne, AbstractConfig newOne) {
408409

409410
protected <C extends AbstractConfig> String generateConfigId(C config) {
410411
String tagName = getTagName(config.getClass());
411-
int idx = configIdIndexes
412-
.computeIfAbsent(tagName, clazz -> new AtomicInteger(0))
412+
int idx = ConcurrentHashMapUtils.computeIfAbsent(configIdIndexes, tagName, clazz -> new AtomicInteger(0))
413413
.incrementAndGet();
414414
return tagName + "#" + idx;
415415
}

dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceMetadata.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public class ServiceMetadata extends BaseServiceMetadata {
4141
/**
4242
* used locally
4343
*/
44-
private final Map<String, Object> attributeMap = new ConcurrentHashMap<>();
44+
private final ConcurrentHashMap<String, Object> attributeMap = new ConcurrentHashMap<>();
4545

4646
public ServiceMetadata(String serviceInterfaceName, String group, String version, Class<?> serviceType) {
4747
this.serviceInterfaceName = serviceInterfaceName;
@@ -63,7 +63,7 @@ public Map<String, Object> getAttachments() {
6363
return attachments;
6464
}
6565

66-
public Map<String, Object> getAttributeMap() {
66+
public ConcurrentHashMap<String, Object> getAttributeMap() {
6767
return attributeMap;
6868
}
6969

dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.dubbo.common.url.component.ServiceConfigURL;
3131
import org.apache.dubbo.common.utils.ClassUtils;
3232
import org.apache.dubbo.common.utils.CollectionUtils;
33+
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
3334
import org.apache.dubbo.common.utils.ConfigUtils;
3435
import org.apache.dubbo.common.utils.NetUtils;
3536
import org.apache.dubbo.common.utils.StringUtils;
@@ -158,7 +159,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
158159
/**
159160
* The exported services
160161
*/
161-
private final Map<RegisterTypeEnum, List<Exporter<?>>> exporters = new ConcurrentHashMap<>();
162+
private final ConcurrentHashMap<RegisterTypeEnum, List<Exporter<?>>> exporters = new ConcurrentHashMap<>();
162163

163164
private final List<ServiceListener> serviceListeners = new ArrayList<>();
164165

@@ -969,8 +970,7 @@ private void doExportUrl(URL url, boolean withMetaData, RegisterTypeEnum registe
969970
invoker = new DelegateProviderMetaDataInvoker(invoker, this);
970971
}
971972
Exporter<?> exporter = protocolSPI.export(invoker);
972-
exporters
973-
.computeIfAbsent(registerType, k -> new CopyOnWriteArrayList<>())
973+
ConcurrentHashMapUtils.computeIfAbsent(exporters, registerType, k -> new CopyOnWriteArrayList<>())
974974
.add(exporter);
975975
}
976976

dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
2424
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
2525
import org.apache.dubbo.common.logger.LoggerFactory;
26+
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
2627
import org.apache.dubbo.common.utils.StringUtils;
2728
import org.apache.dubbo.common.utils.SystemPropertyConfigUtils;
2829
import org.apache.dubbo.metrics.config.event.ConfigCenterEvent;
@@ -167,7 +168,8 @@ private String getAddressWithProtocolPrefix(URL url) {
167168
*/
168169
@Override
169170
public void addListener(String key, String group, ConfigurationListener listener) {
170-
ApolloListener apolloListener = listeners.computeIfAbsent(group + key, k -> createTargetListener(key, group));
171+
ApolloListener apolloListener =
172+
ConcurrentHashMapUtils.computeIfAbsent(listeners, group + key, k -> createTargetListener(key, group));
171173
apolloListener.addListener(listener);
172174
dubboConfig.addChangeListener(apolloListener, Collections.singleton(key));
173175
}

dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/AbstractServiceNameMapping.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@
2121
import org.apache.dubbo.common.logger.LoggerFactory;
2222
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
2323
import org.apache.dubbo.common.utils.CollectionUtils;
24+
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
2425
import org.apache.dubbo.common.utils.StringUtils;
2526
import org.apache.dubbo.config.ApplicationConfig;
2627
import org.apache.dubbo.rpc.model.ApplicationModel;
2728

2829
import java.util.HashSet;
29-
import java.util.Map;
3030
import java.util.Optional;
3131
import java.util.Set;
3232
import java.util.TreeSet;
@@ -50,7 +50,7 @@ public abstract class AbstractServiceNameMapping implements ServiceNameMapping {
5050
protected final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(getClass());
5151
protected ApplicationModel applicationModel;
5252
private final MappingCacheManager mappingCacheManager;
53-
private final Map<String, Set<MappingListener>> mappingListeners = new ConcurrentHashMap<>();
53+
private final ConcurrentHashMap<String, Set<MappingListener>> mappingListeners = new ConcurrentHashMap<>();
5454
// mapping lock is shared among registries of the same application.
5555
private final ConcurrentMap<String, ReentrantLock> mappingLocks = new ConcurrentHashMap<>();
5656

@@ -198,7 +198,7 @@ public Set<String> removeCachedMapping(String serviceKey) {
198198
}
199199

200200
public Lock getMappingLock(String key) {
201-
return mappingLocks.computeIfAbsent(key, _k -> new ReentrantLock());
201+
return ConcurrentHashMapUtils.computeIfAbsent(mappingLocks, key, _k -> new ReentrantLock());
202202
}
203203

204204
protected void removeMappingLock(String key) {
@@ -239,8 +239,8 @@ public Set<String> call() throws Exception {
239239
String mappingKey = ServiceNameMapping.buildMappingKey(subscribedURL);
240240
if (listener != null) {
241241
mappedServices = toTreeSet(getAndListen(subscribedURL, listener));
242-
Set<MappingListener> listeners =
243-
mappingListeners.computeIfAbsent(mappingKey, _k -> new HashSet<>());
242+
Set<MappingListener> listeners = ConcurrentHashMapUtils.computeIfAbsent(
243+
mappingListeners, mappingKey, _k -> new HashSet<>());
244244
listeners.add(listener);
245245
if (CollectionUtils.isNotEmpty(mappedServices)) {
246246
if (notifyAtFirstTime) {

dubbo-metadata/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.dubbo.common.config.configcenter.ConfigItem;
2323
import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
2424
import org.apache.dubbo.common.constants.LoggerCodeConstants;
25+
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
2526
import org.apache.dubbo.common.utils.JsonUtils;
2627
import org.apache.dubbo.common.utils.MD5Utils;
2728
import org.apache.dubbo.common.utils.StringUtils;
@@ -79,9 +80,9 @@ public class NacosMetadataReport extends AbstractMetadataReport {
7980
*/
8081
private String group;
8182

82-
private Map<String, NacosConfigListener> watchListenerMap = new ConcurrentHashMap<>();
83+
private ConcurrentHashMap<String, NacosConfigListener> watchListenerMap = new ConcurrentHashMap<>();
8384

84-
private Map<String, MappingDataListener> casListenerMap = new ConcurrentHashMap<>();
85+
private ConcurrentHashMap<String, MappingDataListener> casListenerMap = new ConcurrentHashMap<>();
8586

8687
private MD5Utils md5Utils = new MD5Utils();
8788

@@ -336,8 +337,8 @@ private String getConfig(String dataId, String group) {
336337
}
337338

338339
private void addCasServiceMappingListener(String serviceKey, String group, MappingListener listener) {
339-
MappingDataListener mappingDataListener = casListenerMap.computeIfAbsent(
340-
buildListenerKey(serviceKey, group), k -> new MappingDataListener(serviceKey, group));
340+
MappingDataListener mappingDataListener = ConcurrentHashMapUtils.computeIfAbsent(
341+
casListenerMap, buildListenerKey(serviceKey, group), k -> new MappingDataListener(serviceKey, group));
341342
mappingDataListener.addListeners(listener);
342343
addListener(serviceKey, DEFAULT_MAPPING_GROUP, mappingDataListener);
343344
}
@@ -355,8 +356,8 @@ private void removeCasServiceMappingListener(String serviceKey, String group, Ma
355356

356357
public void addListener(String key, String group, ConfigurationListener listener) {
357358
String listenerKey = buildListenerKey(key, group);
358-
NacosConfigListener nacosConfigListener =
359-
watchListenerMap.computeIfAbsent(listenerKey, k -> createTargetListener(key, group));
359+
NacosConfigListener nacosConfigListener = ConcurrentHashMapUtils.computeIfAbsent(
360+
watchListenerMap, listenerKey, k -> createTargetListener(key, group));
360361
nacosConfigListener.addListener(listener);
361362
try {
362363
configService.addListener(key, group, nacosConfigListener);

0 commit comments

Comments
 (0)