Unsafe allocation for reflective type adapters.
This commit is contained in:
parent
b922500c23
commit
98aa124589
@ -18,6 +18,7 @@ package com.google.gson;
|
|||||||
|
|
||||||
import com.google.gson.internal.$Gson$Types;
|
import com.google.gson.internal.$Gson$Types;
|
||||||
|
|
||||||
|
import com.google.gson.internal.UnsafeAllocator;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson.internal;
|
||||||
|
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectStreamClass;
|
import java.io.ObjectStreamClass;
|
||||||
@ -27,7 +27,7 @@ import java.lang.reflect.Method;
|
|||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
* @author Jesse Wilson
|
* @author Jesse Wilson
|
||||||
*/
|
*/
|
||||||
abstract class UnsafeAllocator {
|
public abstract class UnsafeAllocator {
|
||||||
public abstract <T> T newInstance(Class<T> c) throws Exception;
|
public abstract <T> T newInstance(Class<T> c) throws Exception;
|
||||||
|
|
||||||
public static UnsafeAllocator create() {
|
public static UnsafeAllocator create() {
|
@ -17,6 +17,7 @@
|
|||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
import com.google.gson.internal.$Gson$Types;
|
import com.google.gson.internal.$Gson$Types;
|
||||||
|
import com.google.gson.internal.UnsafeAllocator;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
@ -35,24 +36,37 @@ import java.util.Map;
|
|||||||
public final class ReflectiveTypeAdapter<T> extends TypeAdapter<T> {
|
public final class ReflectiveTypeAdapter<T> extends TypeAdapter<T> {
|
||||||
public static final Factory FACTORY = new FactoryImpl();
|
public static final Factory FACTORY = new FactoryImpl();
|
||||||
|
|
||||||
|
private static final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
|
||||||
|
private final Class<? super T> rawType;
|
||||||
private final Constructor<? super T> constructor;
|
private final Constructor<? super T> constructor;
|
||||||
private final Map<String, BoundField> map;
|
private final Map<String, BoundField> map;
|
||||||
private final BoundField[] boundFields;
|
private final BoundField[] boundFields;
|
||||||
|
|
||||||
ReflectiveTypeAdapter(Constructor<? super T> constructor, Map<String, BoundField> map) {
|
ReflectiveTypeAdapter(Class<? super T> rawType, Constructor<? super T> constructor, Map<String, BoundField> map) {
|
||||||
|
this.rawType = rawType;
|
||||||
this.constructor = constructor;
|
this.constructor = constructor;
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.boundFields = map.values().toArray(new BoundField[map.size()]);
|
this.boundFields = map.values().toArray(new BoundField[map.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") // the '? super T' is a raw T (the only kind we can construct)
|
||||||
public T read(JsonReader reader) throws IOException {
|
public T read(JsonReader reader) throws IOException {
|
||||||
if (reader.peek() == JsonToken.NULL) {
|
if (reader.peek() == JsonToken.NULL) {
|
||||||
reader.nextNull(); // TODO: does this belong here?
|
reader.nextNull(); // TODO: does this belong here?
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") // the '? super T' is a raw T (the only kind we can construct)
|
T instance;
|
||||||
T instance = (T) MiniGson.newInstance(constructor);
|
if (constructor != null) {
|
||||||
|
instance = (T) MiniGson.newInstance(constructor);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
instance = (T) unsafeAllocator.newInstance(rawType);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(("Unable to invoke no-args constructor for " + rawType.getName()
|
||||||
|
+ ". Register an InstanceCreator with Gson for this type may fix this problem."), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: null out the other fields?
|
// TODO: null out the other fields?
|
||||||
|
|
||||||
@ -128,15 +142,13 @@ public final class ReflectiveTypeAdapter<T> extends TypeAdapter<T> {
|
|||||||
return null; // it's a primitive!
|
return null; // it's a primitive!
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use Joel's constructor calling code (with setAccessible)
|
Constructor<? super T> constructor = null;
|
||||||
Constructor<? super T> constructor;
|
|
||||||
try {
|
try {
|
||||||
constructor = raw.getDeclaredConstructor();
|
constructor = raw.getDeclaredConstructor();
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException ignored) {
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ReflectiveTypeAdapter<T>(constructor, getBoundFields(context, type, raw));
|
return new ReflectiveTypeAdapter<T>(raw, constructor, getBoundFields(context, type, raw));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, BoundField> getBoundFields(
|
private Map<String, BoundField> getBoundFields(
|
||||||
|
Loading…
Reference in New Issue
Block a user