hessian 反序列化问题

有class 比如

class Test{

private TestArrayList list=new TestArrayList("");

public static void main(String args[]){

Test t=new Test();

 byte[] b=hessian encode ;

 Test r =(Test)hessian decode

}

}

class TestArrayList extends ArrayList{

  public TestArrayList(String a){}

}

反序列化后Test对象里的list不再是TestArrayList,而是 ArrayList类型

分析hessian反序列化源码

Hessian2Input.java

public Object readObject(Class cl){
  //省略
    case 0x70: case 0x71: case 0x72: case 0x73:
    case 0x74: case 0x75: case 0x76: case 0x77:
      {
    int length = tag - 0x70;

    String type = readType();
      
    Deserializer reader;
        
    reader = findSerializerFactory().getListDeserializer(type, cl);
    //关键处
    Object v = reader.readLengthList(this, length);

    return v;
      }    

}

跳转到

CollectionDeserializer.java

public Object readLengthList(AbstractHessianInput in, int length)
    throws IOException
  {
    Collection list = createList();

    in.addRef(list);

    for (; length > 0; length--)
      list.add(in.readObject());

    return list;
  }

private Collection createList()
    throws IOException
  {
    Collection list = null;
    
    if (_type == null)
      list = new ArrayList();
    else if (! _type.isInterface()) {
      try {
//关键处 list
= (Collection) _type.newInstance(); } catch (Exception e) { } } if (list != null) { } else if (SortedSet.class.isAssignableFrom(_type)) list = new TreeSet(); else if (Set.class.isAssignableFrom(_type)) list = new HashSet(); else if (List.class.isAssignableFrom(_type)) list = new ArrayList(); else if (Collection.class.isAssignableFrom(_type)) list = new ArrayList(); //省略 }
list = (Collection) _type.newInstance();尝试调用TestArrayList的无参构造函数,但因为没有无参构造函数,抛出异常,走到下面的list = new ArrayList();逻辑

我们看看newInstance()做了什么事情
public T newInstance()
        throws InstantiationException, IllegalAccessException
    {
        if (System.getSecurityManager() != null) {
            checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
        }

        // NOTE: the following code may not be strictly correct under
        // the current Java memory model.

        // Constructor lookup
        if (cachedConstructor == null) {
            if (this == Class.class) {
                throw new IllegalAccessException(
                    "Can not call newInstance() on the Class for java.lang.Class"
                );
            }
            try {
                Class<?>[] empty = {};
                final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
  //省略
}

private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
                                        int which) throws NoSuchMethodException
    {
        Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
//这里parameterTypes是空数组,constructors不为空
        for (Constructor<T> constructor : constructors) {
//数组比较长度不一致,抛出异常
            if (arrayContentsEq(parameterTypes,
                                constructor.getParameterTypes())) {
                return getReflectionFactory().copyConstructor(constructor);
            }
        }
        throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
    }

 

因此我们如果调用hessian序列化对象的时候,一定要注意对象里面的自定义属性是否有默认构造函数,不然会引起奇怪的问题

 

posted on 2018-04-20 11:38  devilwind  阅读(2834)  评论(0编辑  收藏  举报