Skip to content

Commit

Permalink
bug fixed for issue alibaba#849 . improved TypeRerence Performance.
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed Oct 11, 2016
1 parent c43a1b3 commit e456218
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 2 deletions.
34 changes: 32 additions & 2 deletions src/main/java/com/alibaba/fastjson/TypeReference.java
Expand Up @@ -3,6 +3,8 @@
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import com.alibaba.fastjson.util.ParameterizedTypeImpl;

Expand All @@ -22,6 +24,8 @@
* parameters, such as {@code Class<?>} or {@code List<? extends CharSequence>}.
*/
public class TypeReference<T> {
static ConcurrentMap<Class<?>, ConcurrentMap<Type, ConcurrentMap<Type, Type>>> classTypeCache
= new ConcurrentHashMap<Class<?>, ConcurrentMap<Type, ConcurrentMap<Type, Type>>>(16, 0.75f, 1);

protected final Type type;

Expand All @@ -44,7 +48,8 @@ protected TypeReference(){
* @param actualTypeArguments
*/
protected TypeReference(Type... actualTypeArguments){
Type superClass = getClass().getGenericSuperclass();
Class<?> thisClass = this.getClass();
Type superClass = thisClass.getGenericSuperclass();

ParameterizedType argType = (ParameterizedType) ((ParameterizedType) superClass).getActualTypeArguments()[0];
Type rawType = argType.getRawType();
Expand All @@ -59,7 +64,32 @@ protected TypeReference(Type... actualTypeArguments){
}
}
}
type = new ParameterizedTypeImpl(argTypes, this.getClass(), rawType);

if (actualTypeArguments.length == 1 && argTypes.length == 1) {
ConcurrentMap<Type, ConcurrentMap<Type, Type>> classCache = classTypeCache.get(thisClass);
if (classCache == null) {
classTypeCache.putIfAbsent(thisClass, new ConcurrentHashMap<Type, ConcurrentMap<Type, Type>>(16, 0.75f, 1));
classCache = classTypeCache.get(thisClass);
}

ConcurrentMap<Type, Type> typeCached = classCache.get(argType);
if (typeCached == null) {
classCache.putIfAbsent(argType, new ConcurrentHashMap<Type, Type>(16, 0.75f, 1));
typeCached = classCache.get(argType);
}

Type actualTypeArgument = actualTypeArguments[0];

Type cachedType = typeCached.get(actualTypeArgument);
if (cachedType == null) {
typeCached.putIfAbsent(actualTypeArgument, actualTypeArgument);
cachedType = typeCached.get(actualTypeArgument);
}

type = cachedType;
} else {
type = new ParameterizedTypeImpl(argTypes, thisClass, rawType);
}
}

/**
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/com/alibaba/fastjson/util/ParameterizedTypeImpl.java
Expand Up @@ -2,6 +2,7 @@

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;

public class ParameterizedTypeImpl implements ParameterizedType {

Expand All @@ -27,4 +28,18 @@ public Type getRawType() {
return rawType;
}


@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

ParameterizedTypeImpl that = (ParameterizedTypeImpl) o;

// Probably incorrect - comparing Object[] arrays with Arrays.equals
if (!Arrays.equals(actualTypeArguments, that.actualTypeArguments)) return false;
if (ownerType != null ? !ownerType.equals(that.ownerType) : that.ownerType != null) return false;
return rawType != null ? rawType.equals(that.rawType) : that.rawType == null;

}
}
28 changes: 28 additions & 0 deletions src/test/java/com/alibaba/json/bvt/TypeReferenceTest10.java
@@ -0,0 +1,28 @@
package com.alibaba.json.bvt;

import com.alibaba.fastjson.TypeReference;
import junit.framework.TestCase;
import org.junit.Assert;

import java.lang.reflect.Type;

/**
* Created by wenshao on 2016/10/11.
*/
public class TypeReferenceTest10 extends TestCase {
public void test_same() throws Exception {
Type type1 = getType();
Type type2 = getType();

assertEquals(type1, type2);
assertSame(type1, type2);
}

Type getType() {
return new TypeReference<Model<Integer>>() {}.getType();
}

public static class Model<T> {
public T value;
}
}
33 changes: 33 additions & 0 deletions src/test/java/com/alibaba/json/bvt/TypeReferenceTest11.java
@@ -0,0 +1,33 @@
package com.alibaba.json.bvt;

import com.alibaba.fastjson.TypeReference;
import junit.framework.TestCase;

import java.lang.reflect.Type;

/**
* Created by wenshao on 2016/10/11.
*/
public class TypeReferenceTest11 extends TestCase {
public void test_same() throws Exception {
Type type1 = getType(Integer.class);
Type type2 = getType(Integer.class);

assertEquals(type1, type2);
assertSame(type1, type2);
}

<T> Type getType(Type type) {
return new TypeReference<Response<T>>(type) {}.getType();
}

public static class Model<T> {
public T value;
}

public static class Response<T> {
public T data;
}


}

0 comments on commit e456218

Please sign in to comment.