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序列化對象的時候,一定要注意對象里面的自定義屬性是否有默認構造函數,不然會引起奇怪的問題

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM