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