hessian deserialization problem

There are classes such as

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){}

}

After deserialization, the list in the Test object is no longer TestArrayList, but an ArrayList type

Analyze hessian deserialization source code

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;
      }    

}

redirect to

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(); Try to call the no-argument constructor of TestArrayList, but because there is no no-argument constructor, an exception is thrown, go to the following list = new ArrayList(); Logic

let's look at newInstance() what did you do
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);
   // omitted 
} 

private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
                                        int which) throws NoSuchMethodException
    {
        Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
//here parameterTypes is an empty array, constructors are not empty
        for (Constructor<T> constructor : constructors) {
//Array comparison length Inconsistent, throw exception
            if (arrayContentsEq(parameterTypes,
                                constructor.getParameterTypes())) {
                return getReflectionFactory().copyConstructor(constructor);
            }
        }
        throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
    }

 

Therefore, if we call the hessian serialized object, we must pay attention to whether the custom attribute in the object has a default constructor, otherwise it will cause strange problems

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326012713&siteId=291194637