Android Gson缓存机制与重复类型处理优化原理剖析(22)

132 阅读7分钟

Android Gson缓存机制与重复类型处理优化原理剖析

一、Gson缓存机制概述

1.1 缓存机制的重要性

在Android应用开发中,JSON序列化和反序列化是常见操作。Gson作为主流的JSON处理库,其性能直接影响应用的响应速度和资源消耗。缓存机制在Gson中扮演着关键角色,主要解决以下问题:

  1. 反射开销:Java反射机制在运行时获取类的字段和方法信息,这一过程消耗大量CPU资源
  2. 重复解析:对于相同类型的序列化/反序列化操作,避免重复的类型分析和适配器创建
  3. 内存占用:通过复用已创建的对象和数据结构,减少内存分配和垃圾回收压力

1.2 核心缓存组件

Gson的缓存机制主要由以下组件构成:

  1. TypeToken:封装类型信息,包括泛型参数,用于唯一标识类型
  2. TypeAdapterFactory:工厂链,负责创建和缓存TypeAdapter实例
  3. TypeAdapter:负责具体类型的序列化和反序列化
  4. ThreadLocal:线程局部存储,缓存线程内常用的对象
  5. WeakHashMap:弱引用缓存,避免内存泄漏

1.3 缓存的生命周期

Gson的缓存对象主要在以下两个阶段起作用:

  1. 初始化阶段:在Gson实例创建时,部分基础适配器会被预加载到缓存中
  2. 运行时阶段:首次处理某个类型时,相关信息会被缓存;后续处理相同类型时直接复用

二、TypeToken与类型识别

2.1 TypeToken的作用

TypeToken是Gson中用于表示泛型类型的核心类,其主要功能包括:

  1. 捕获泛型信息:通过子类化TypeToken,可以在运行时保留泛型类型信息
  2. 生成唯一标识:为不同类型生成哈希值和相等性比较,用于缓存查找
  3. 类型解析:解析复杂类型,包括数组、集合和嵌套泛型

2.2 TypeToken源码分析

public class TypeToken<T> {
  final Type type; // 存储具体的类型信息
  final int hashCode; // 类型的哈希值,用于缓存查找

  protected TypeToken() {
    // 获取子类的泛型超类
    this.type = getSuperclassTypeParameter(getClass());
    this.hashCode = type.hashCode();
  }

  TypeToken(Type type) {
    // 直接从Type对象创建TypeToken
    this.type = $Gson$Types.canonicalize($Gson$Preconditions.checkNotNull(type));
    this.hashCode = this.type.hashCode();
  }

  // 获取超类的泛型参数类型
  static Type getSuperclassTypeParameter(Class<?> subclass) {
    Type superclass = subclass.getGenericSuperclass();
    if (superclass instanceof Class) {
      throw new RuntimeException("Missing type parameter.");
    }
    // 强制转换为ParameterizedType获取泛型参数
    ParameterizedType parameterized = (ParameterizedType) superclass;
    return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
  }

  // 获取原始类型
  public final Class<? super T> getRawType() {
    return $Gson$Types.getRawType(type);
  }

  // 获取完整类型信息
  public final Type getType() {
    return type;
  }

  // 重写equals方法,用于类型比较
  @Override public final boolean equals(Object o) {
    return o instanceof TypeToken<?>
        && $Gson$Types.equals(type, ((TypeToken<?>) o).type);
  }

  // 重写hashCode方法,用于缓存键
  @Override public final int hashCode() {
    return hashCode;
  }

  // 其他辅助方法...
}

2.3 类型规范与规范化

Gson通过$Gson$Types.canonicalize()方法对类型进行规范化处理,确保相同类型生成一致的表示:

// $Gson$Types类中的关键方法
static Type canonicalize(Type type) {
  // 处理数组类型
  if (type instanceof GenericArrayType) {
    GenericArrayType array = (GenericArrayType) type;
    Type componentType = array.getGenericComponentType();
    Type canonicalComponentType = canonicalize(componentType);
    if (componentType != canonicalComponentType) {
      return new GenericArrayTypeImpl(canonicalComponentType);
    }
    return array;
  }

  // 处理参数化类型
  if (type instanceof ParameterizedType) {
    ParameterizedType parameterized = (ParameterizedType) type;
    Type ownerType = parameterized.getOwnerType();
    Type canonicalOwnerType = canonicalize(ownerType);

    Type[] typeArguments = parameterized.getActualTypeArguments();
    Type[] canonicalTypeArguments = new Type[typeArguments.length];
    boolean changed = false;
    for (int i = 0; i < typeArguments.length; i++) {
      canonicalTypeArguments[i] = canonicalize(typeArguments[i]);
      if (canonicalTypeArguments[i] != typeArguments[i]) {
        changed = true;
      }
    }

    if (changed || canonicalOwnerType != ownerType) {
      return new ParameterizedTypeImpl(
          canonicalOwnerType, parameterized.getRawType(), canonicalTypeArguments);
    }
    return parameterized;
  }

  // 处理WildcardType等其他类型...

  return type;
}

2.4 类型缓存键的生成

Gson使用TypeToken作为缓存键,确保即使是相同类型的不同表示也能被正确识别:

// Gson类中的类型适配器缓存
private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache
    = new ConcurrentHashMap<TypeToken<?>, TypeAdapter<?>>();

// 获取适配器时使用TypeToken作为键
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
  // 先从缓存中查找
  TypeAdapter<?> cached = typeTokenCache.get(type);
  if (cached != null) {
    return (TypeAdapter<T>) cached;
  }

  // 如果缓存未命中,则创建新的适配器并缓存
  // ...
}

三、TypeAdapter缓存机制

3.1 TypeAdapter工厂链

Gson使用工厂链模式创建TypeAdapter实例,每个工厂负责特定类型的适配器创建:

// Gson类中的工厂链
private final List<TypeAdapterFactory> factories;

// 创建Gson实例时初始化工厂链
Gson(Builder builder) {
  // 初始化工厂链,顺序很重要,先注册的工厂优先级高
  this.factories = new ArrayList<TypeAdapterFactory>();
  
  // 添加内置工厂
  factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
  factories.add(ObjectTypeAdapter.FACTORY);
  
  // 添加用户注册的工厂
  factories.addAll(builder.factories);
  
  // 添加反射相关工厂
  factories.add(new ReflectiveTypeAdapterFactory(
      constructorConstructor, fieldNamingStrategy, exclusionStrategies));
}

3.2 TypeAdapter缓存流程

当请求一个TypeAdapter时,Gson会按以下流程处理:

// Gson类中的getAdapter方法
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
  // 先从缓存中查找
  TypeAdapter<?> cached = typeTokenCache.get(type);
  if (cached != null) {
    return (TypeAdapter<T>) cached;
  }

  // 缓存未命中,使用同步块避免重复创建
  synchronized (typeTokenCache) {
    cached = typeTokenCache.get(type);
    if (cached != null) {
      return (TypeAdapter<T>) cached;
    }

    // 遍历工厂链,尝试创建适配器
    TypeAdapter<T> adapter = null;
    for (TypeAdapterFactory factory : factories) {
      adapter = factory.create(this, type);
      if (adapter != null) {
        break;
      }
    }

    if (adapter == null) {
      throw new IllegalArgumentException("Gson cannot handle " + type);
    }

    // 将新创建的适配器放入缓存
    typeTokenCache.put(type, adapter);
    return adapter;
  }
}

3.3 适配器的单例特性

Gson为每种类型只创建一个TypeAdapter实例,并在整个生命周期中复用:

// ReflectiveTypeAdapterFactory创建适配器的方法
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
  Class<? super T> rawType = typeToken.getRawType();
  
  // 检查是否为可处理的类型
  if (!Object.class.isAssignableFrom(rawType)) {
    return null;
  }

  // 创建反射适配器
  return (TypeAdapter<T>) new Adapter<T>(
      gson, rawType, getBoundFields(gson, typeToken, rawType));
}

// Adapter类是反射类型适配器,每个类型只创建一个实例
private static final class Adapter<T> extends TypeAdapter<T> {
  private final Class<?> type;
  private final Map<String, BoundField> boundFields;
  
  Adapter(Gson gson, Class<?> type, Map<String, BoundField> boundFields) {
    this.type = type;
    this.boundFields = boundFields;
  }
  
  // 实现读写方法...
}

四、重复类型处理优化

4.1 循环引用检测

Gson通过ThreadLocal维护一个栈结构,用于检测对象图中的循环引用:

// 在ReflectiveTypeAdapterFactory.Adapter类中
private final ThreadLocal<Stack<JsonElement>> serializeStack
    = new ThreadLocal<Stack<JsonElement>>() {
  @Override protected Stack<JsonElement> initialValue() {
    return new Stack<JsonElement>();
  }
};

// 序列化前检查循环引用
@Override public void write(JsonWriter out, T value) throws IOException {
  if (value == null) {
    out.nullValue();
    return;
  }

  // 检查是否正在序列化该对象(循环引用)
  Stack<JsonElement> stack = serializeStack.get();
  if (stack.contains(value)) {
    throw new JsonIOException("Circular reference detected");
  }

  try {
    stack.push(value);
    // 执行实际序列化
    JsonObject jsonObject = new JsonObject();
    for (BoundField boundField : boundFields.values()) {
      if (boundField.writeField(value)) {
        boundField.writeTo(jsonObject, value);
      }
    }
    Streams.write(jsonObject, out);
  } finally {
    stack.pop();
  }
}

4.2 嵌套类型处理

对于嵌套类型,Gson会递归处理并复用已有的适配器:

// 在ReflectiveTypeAdapterFactory.BoundField类中
abstract static class BoundField {
  // 字段名称
  final String name;
  // 是否序列化该字段
  final boolean serialized;
  // 是否反序列化该字段
  final boolean deserialized;

  protected BoundField(String name, boolean serialized, boolean deserialized) {
    this.name = name;
    this.serialized = serialized;
    this.deserialized = deserialized;
  }

  // 写入字段值到JSON
  abstract void writeTo(JsonObject jsonObject, Object value) throws IOException, IllegalAccessException;
  
  // 从JSON读取字段值
  abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException;
}

// 实现类处理具体字段的读写
private static final class SingleField extends BoundField {
  private final Field field;
  private final TypeAdapter<?> typeAdapter;

  SingleField(String name, Field field, TypeAdapter<?> typeAdapter,
      boolean serialize, boolean deserialize) {
    super(name, serialize, deserialize);
    this.field = field;
    this.typeAdapter = typeAdapter;
  }

  @Override void writeTo(JsonObject jsonObject, Object value) throws IOException, IllegalAccessException {
    Object fieldValue = field.get(value);
    JsonElement element = typeAdapter.toJsonTree(fieldValue);
    jsonObject.add(name, element);
  }

  @Override void read(JsonReader reader, Object value) throws IOException, IllegalAccessException {
    Object fieldValue = typeAdapter.read(reader);
    if (fieldValue != null || !isPrimitive) {
      field.set(value, fieldValue);
    }
  }
}

4.3 集合与Map优化

对于集合和Map类型,Gson会优化处理以避免重复操作:

// CollectionTypeAdapterFactory处理集合类型
public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {
  private final ConstructorConstructor constructorConstructor;

  public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
    this.constructorConstructor = constructorConstructor;
  }

  @Override
  public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
    Type type = typeToken.getType();
    
    // 检查是否为集合类型
    Class<? super T> rawType = typeToken.getRawType();
    if (!Collection.class.isAssignableFrom(rawType)) {
      return null;
    }

    // 获取集合元素类型
    Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
    TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType));

    // 创建集合构造器
    ObjectConstructor<T> constructor = constructorConstructor.get(typeToken);

    // 创建集合适配器
    @SuppressWarnings({"unchecked", "rawtypes"})
    TypeAdapter<T> result = new Adapter(
        gson, elementType, (TypeAdapter) elementTypeAdapter, constructor);
    return result;
  }

  private static final class Adapter<E> extends TypeAdapter<Collection<E>> {
    private final TypeAdapter<E> elementTypeAdapter;
    private final ObjectConstructor<? extends Collection<E>> constructor;

    Adapter(Gson context, Type elementType,
        TypeAdapter<E> elementTypeAdapter,
        ObjectConstructor<? extends Collection<E>> constructor) {
      this.elementTypeAdapter = new TypeAdapterRuntimeTypeWrapper<>(
          context, elementTypeAdapter, elementType);
      this.constructor = constructor;
    }

    @Override public void write(JsonWriter out, Collection<E> collection) throws IOException {
      if (collection == null) {
        out.nullValue();
        return;
      }

      out.beginArray();
      for (E element : collection) {
        elementTypeAdapter.write(out, element);
      }
      out.endArray();
    }

    @Override public Collection<E> read(JsonReader in) throws IOException {
      if (in.peek() == JsonToken.NULL) {
        in.nextNull();
        return null;
      }

      Collection<E> collection = constructor.construct();
      in.beginArray();
      while (in.hasNext()) {
        E instance = elementTypeAdapter.read(in);
        collection.add(instance);
      }
      in.endArray();
      return collection;
    }
  }
}

五、弱引用与内存管理

5.1 弱引用缓存

Gson使用WeakHashMap缓存某些对象,允许在内存不足时被垃圾回收:

// 在$Gson$Types类中
private static final WeakHashMap<Type, Type> canonicalTypes
    = new WeakHashMap<Type, Type>();

// 获取规范类型的方法
static Type canonicalize(Type type) {
  // 先从弱引用缓存中查找
  synchronized (canonicalTypes) {
    Type canonical = canonicalTypes.get(type);
    if (canonical != null) {
      return canonical;
    }

    // 缓存未命中,创建规范类型
    Type result = canonicalizeInternal(type);
    
    // 将结果放入缓存
    canonicalTypes.put(type, result);
    return result;
  }
}

5.2 内存优化策略

Gson通过以下策略优化内存使用:

  1. 对象复用:如JsonWriter、JsonReader等对象在线程局部存储中复用
  2. 弱引用缓存:使用WeakHashMap存储非关键数据,允许垃圾回收
  3. 延迟初始化:某些组件在首次使用时才初始化
  4. 避免重复解析:类型信息和适配器只解析一次并缓存
// 在Gson类中
private final ThreadLocal<JsonWriter> jsonWriterThreadLocal =
    new ThreadLocal<JsonWriter>() {
  @Override protected JsonWriter initialValue() {
    return new JsonWriter(new StringWriter());
  }
};

// 获取线程局部的JsonWriter
JsonWriter getJsonWriter(Writer writer) {
  JsonWriter jsonWriter = jsonWriterThreadLocal.get();
  jsonWriter.setWriter(writer);
  return jsonWriter;
}