Skip to content

Commit

Permalink
fixed for issue alibaba#849(improved TypeRerence Performance) and ali…
Browse files Browse the repository at this point in the history
  • Loading branch information
wuwen5 committed Dec 7, 2016
1 parent 3999ee9 commit e1e49f6
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 27 deletions.
38 changes: 11 additions & 27 deletions src/main/java/com/alibaba/fastjson/TypeReference.java
Expand Up @@ -24,8 +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);
static ConcurrentMap<Type, Type> classTypeCache
= new ConcurrentHashMap<Type, Type>(16, 0.75f, 1);

protected final Type type;

Expand All @@ -42,7 +42,7 @@ protected TypeReference(){

type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}

/**
* @since 1.2.9
* @param actualTypeArguments
Expand All @@ -54,7 +54,7 @@ protected TypeReference(Type... actualTypeArguments){
ParameterizedType argType = (ParameterizedType) ((ParameterizedType) superClass).getActualTypeArguments()[0];
Type rawType = argType.getRawType();
Type[] argTypes = argType.getActualTypeArguments();

int actualIndex = 0;
for (int i = 0; i < argTypes.length; ++i) {
if (argTypes[i] instanceof TypeVariable) {
Expand All @@ -65,31 +65,15 @@ protected TypeReference(Type... actualTypeArguments){
}
}

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 key = new ParameterizedTypeImpl(argTypes, thisClass, rawType);
Type cachedType = classTypeCache.get(key);
if (cachedType == null) {
classTypeCache.putIfAbsent(key, key);
cachedType = classTypeCache.get(key);
}

Type actualTypeArgument = actualTypeArguments[0];
type = cachedType;

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
33 changes: 33 additions & 0 deletions src/test/java/com/alibaba/json/bvt/TypeReferenceTest12.java
@@ -0,0 +1,33 @@
package com.alibaba.json.bvt;

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

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

/**
* Created by wuwen on 2016/12/7.
*/
public class TypeReferenceTest12 extends TestCase {

public void test_same() throws Exception {
ParameterizedType type1 = getType(Integer.class);
ParameterizedType type2 = getType();

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

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

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

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

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

/**
* Created by wuwen on 2016/12/7.
*/
public class Bug_for_issue_937 extends TestCase {

public void test_for_issue() throws Exception {
String json = "{outPara:{name:\"user\"}}";
Out<Info> out = returnOut(json, Info.class);
Assert.assertEquals("user", out.getOutPara().getName());
}

public static <T> Out<T> returnOut(String jsonStr, Class<T> c2) {
return JSON.parseObject(jsonStr, new TypeReference<Out<T>>(c2) {
});
}

public static class Out<T> {
private T outPara;

public void setOutPara(T t) {
outPara = t;
}

public T getOutPara() {
return outPara;
}

public Out() {
}

public Out(T t) {
setOutPara(t);
}
}

public static class Info {
private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
}

0 comments on commit e1e49f6

Please sign in to comment.