Android Gson缓存机制与重复类型处理优化原理剖析
一、Gson缓存机制概述
1.1 缓存机制的重要性
在Android应用开发中,JSON序列化和反序列化是常见操作。Gson作为主流的JSON处理库,其性能直接影响应用的响应速度和资源消耗。缓存机制在Gson中扮演着关键角色,主要解决以下问题:
- 反射开销:Java反射机制在运行时获取类的字段和方法信息,这一过程消耗大量CPU资源
- 重复解析:对于相同类型的序列化/反序列化操作,避免重复的类型分析和适配器创建
- 内存占用:通过复用已创建的对象和数据结构,减少内存分配和垃圾回收压力
1.2 核心缓存组件
Gson的缓存机制主要由以下组件构成:
- TypeToken:封装类型信息,包括泛型参数,用于唯一标识类型
- TypeAdapterFactory:工厂链,负责创建和缓存TypeAdapter实例
- TypeAdapter:负责具体类型的序列化和反序列化
- ThreadLocal:线程局部存储,缓存线程内常用的对象
- WeakHashMap:弱引用缓存,避免内存泄漏
1.3 缓存的生命周期
Gson的缓存对象主要在以下两个阶段起作用:
- 初始化阶段:在Gson实例创建时,部分基础适配器会被预加载到缓存中
- 运行时阶段:首次处理某个类型时,相关信息会被缓存;后续处理相同类型时直接复用
二、TypeToken与类型识别
2.1 TypeToken的作用
TypeToken是Gson中用于表示泛型类型的核心类,其主要功能包括:
- 捕获泛型信息:通过子类化TypeToken,可以在运行时保留泛型类型信息
- 生成唯一标识:为不同类型生成哈希值和相等性比较,用于缓存查找
- 类型解析:解析复杂类型,包括数组、集合和嵌套泛型
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通过以下策略优化内存使用:
- 对象复用:如JsonWriter、JsonReader等对象在线程局部存储中复用
- 弱引用缓存:使用WeakHashMap存储非关键数据,允许垃圾回收
- 延迟初始化:某些组件在首次使用时才初始化
- 避免重复解析:类型信息和适配器只解析一次并缓存
// 在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;
}