From 7abeb1608064abd19129ef7bcaf781dbd3ed26e9 Mon Sep 17 00:00:00 2001 From: Chris Conroy Date: Tue, 27 Oct 2015 20:01:38 -0400 Subject: [PATCH] Thread safe method cache --- .../gson/protobuf/ProtoTypeAdapter.java | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java b/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java index e0c425ca..ff44779f 100644 --- a/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java +++ b/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.CaseFormat; import com.google.common.base.Converter; +import com.google.common.collect.MapMaker; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; @@ -44,10 +45,10 @@ import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentMap; /** * GSON type adapter for protocol buffers that knows how to serialize enums either by using their @@ -190,6 +191,9 @@ public class ProtoTypeAdapter private static final com.google.protobuf.Descriptors.FieldDescriptor.Type ENUM_TYPE = com.google.protobuf.Descriptors.FieldDescriptor.Type.ENUM; + private static final ConcurrentMap, Method>> mapOfMapOfMethods = + new MapMaker().makeMap(); + private final EnumSerialization enumSerialization; private final Converter fieldNameSerializationFormat; private final Set> serializedNameExtensions; @@ -380,18 +384,23 @@ public class ProtoTypeAdapter } } - private static Method getCachedMethod(Class clazz, String methodName) - throws NoSuchMethodException { - if (!mapOfMapOfMethods.containsKey(methodName)) { - mapOfMapOfMethods.put(methodName, new HashMap, Method>()); - } + private static Method getCachedMethod(Class clazz, String methodName, + Class... methodParamTypes) throws NoSuchMethodException { Map, Method> mapOfMethods = mapOfMapOfMethods.get(methodName); - if (!mapOfMethods.containsKey(clazz)) { - mapOfMethods.put(clazz, clazz.getMethod(methodName)); + if (mapOfMethods == null) { + mapOfMethods = new MapMaker().makeMap(); + Map, Method> previous = + mapOfMapOfMethods.putIfAbsent(methodName, mapOfMethods); + mapOfMethods = previous == null ? mapOfMethods : previous; } - return mapOfMethods.get(clazz); + + Method method = mapOfMethods.get(clazz); + if (method == null) { + method = clazz.getMethod(methodName, methodParamTypes); + mapOfMethods.putIfAbsent(clazz, method); + // NB: it doesn't matter which method we return in the event of a race. + } + return method; } - private static Map, Method>> mapOfMapOfMethods = - new HashMap, Method>>(); }