diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index 4027d375..ccdcc2c9 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -115,6 +115,15 @@ public final class Gson { private final Map, TypeAdapter> typeTokenCache = Collections.synchronizedMap(new HashMap, TypeAdapter>()); + /** Indicates whether Gson is in the phase of constructor invocation. It is used to determine + * whether to add a constructor in preconfiguredGeneratedTypeAdapter set or not. */ + private boolean inConstructorPhase = true; + /** List of type adapters that are generated by Gson during its constructor */ + private Set> preconfiguredGeneratedTypeAdapters = new HashSet>(); + /** List of type adapters that are generated by Gson during toJson/fromJson. */ + private final ThreadLocal>> runtimeGeneratedTypeAdapters = + new ThreadLocal>>(); + private final List factories; private final ConstructorConstructor constructorConstructor; @@ -245,6 +254,8 @@ public final class Gson { constructorConstructor, fieldNamingPolicy, excluder)); this.factories = Collections.unmodifiableList(factories); + this.preconfiguredGeneratedTypeAdapters = Collections.unmodifiableSet(preconfiguredGeneratedTypeAdapters); + inConstructorPhase = false; } private TypeAdapter doubleAdapter(boolean serializeSpecialFloatingPointValues) { @@ -907,13 +918,25 @@ public final class Gson { .toString(); } - private final Set> generatedTypeAdapters = new HashSet>(); public static final class $$Internal { public static void addGeneratedTypeAdapter(Gson gson, TypeAdapter typeAdapter) { - gson.generatedTypeAdapters.add(typeAdapter); + if (gson.inConstructorPhase) { + gson.preconfiguredGeneratedTypeAdapters.add(typeAdapter); + } else { + Set> adapters = getRuntimeGeneratedTypeAdapters(gson); + adapters.add(typeAdapter); + } } public static boolean isGeneratedTypeAdapter(Gson gson, TypeAdapter typeAdapter) { - return gson.generatedTypeAdapters.contains(typeAdapter); + boolean generated = gson.preconfiguredGeneratedTypeAdapters.contains(typeAdapter); + if (!generated) generated = getRuntimeGeneratedTypeAdapters(gson).contains(typeAdapter); + return generated; + } + private static Set> getRuntimeGeneratedTypeAdapters(Gson gson) { + Set> adapters = gson.runtimeGeneratedTypeAdapters.get(); + if (adapters == null) adapters = new HashSet>(); + gson.runtimeGeneratedTypeAdapters.set(adapters); + return adapters; } } }