• 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序列化对象的时候,一定要注意对象里面的自定义属性是否有默认构造函数,不然会引起奇怪的问题

  • 相关阅读:
    OleView.exe:查看机器上的COM 组件。
    COM中导出GUID
    进程外组件以及进程间通信方式
    拼接多个 wchar_t *
    wstring to wchar_t*
    BSTR
    GetProcAddress 使用注意事项
    C++和.net的集合类对应
    COM的一些基本概念
    Error Lookup工具
  • 原文地址:https://www.cnblogs.com/devilwind/p/8889394.html
Copyright © 2020-2023  润新知