Added a cache for no-args constructors to avoid expensive reflection everytime an object needs to be instantiated.
This commit is contained in:
parent
861e047a62
commit
6d3e0e92a5
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
|
import com.google.gson.internal.LruCache;
|
||||||
import com.google.gson.internal.Types;
|
import com.google.gson.internal.Types;
|
||||||
import com.google.gson.internal.UnsafeAllocator;
|
import com.google.gson.internal.UnsafeAllocator;
|
||||||
|
|
||||||
|
@ -36,7 +37,22 @@ import java.lang.reflect.Type;
|
||||||
final class MappedObjectConstructor implements ObjectConstructor {
|
final class MappedObjectConstructor implements ObjectConstructor {
|
||||||
private static final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
|
private static final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
|
||||||
|
|
||||||
|
private static final LruCache<Class<?>, Constructor<?>> noArgsConstructorsCache =
|
||||||
|
new LruCache<Class<?>, Constructor<?>>(500);
|
||||||
private final ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreatorMap;
|
private final ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreatorMap;
|
||||||
|
/**
|
||||||
|
* We need a special null value to indicate that the class does not have a no-args constructor.
|
||||||
|
* This helps avoid using reflection over and over again for such classes. For convenience, we
|
||||||
|
* use the no-args constructor of this class itself since this class would never be
|
||||||
|
* deserialized using Gson.
|
||||||
|
*/
|
||||||
|
private static final Constructor<MappedObjectConstructor> NULL_VALUE =
|
||||||
|
getNoArgsConstructorUsingReflection(MappedObjectConstructor.class);
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private MappedObjectConstructor() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
public MappedObjectConstructor(
|
public MappedObjectConstructor(
|
||||||
ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreators) {
|
ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreators) {
|
||||||
|
@ -71,13 +87,27 @@ final class MappedObjectConstructor implements ObjectConstructor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> Constructor<T> getNoArgsConstructor(Class<T> clazz) {
|
private <T> Constructor<T> getNoArgsConstructor(Class<T> clazz) {
|
||||||
try {
|
@SuppressWarnings("unchecked")
|
||||||
Constructor<T> declaredConstructor = clazz.getDeclaredConstructor();
|
Constructor<T> constructor = (Constructor<T>)noArgsConstructorsCache.getElement(clazz);
|
||||||
declaredConstructor.setAccessible(true);
|
if (constructor == NULL_VALUE) {
|
||||||
return declaredConstructor;
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (constructor == null) {
|
||||||
|
constructor = getNoArgsConstructorUsingReflection(clazz);
|
||||||
|
noArgsConstructorsCache.addElement(clazz, constructor);
|
||||||
|
}
|
||||||
|
return constructor == NULL_VALUE ? null : constructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static <T> Constructor<T> getNoArgsConstructorUsingReflection(Class<T> clazz) {
|
||||||
|
try {
|
||||||
|
Constructor<T> constructor = clazz.getDeclaredConstructor();
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
return constructor;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return (Constructor<T>) NULL_VALUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue
Block a user