关于Java私有对象的读取

有些系统通信涉及到跨平台,其中hessian是可以做.net和java平台之间报文,hessian里面有一个最重要的东西就是序列化,但是用过java的人都知道序列化的时候如果是私有对象的,是不可能被外部对象读取,存在get/set方法也不是必须的,因为做为通信的对象完全可能不存在该方法,如果一个对象可以被序列化及反序列化那么就一定存在一种方式去跨过java的语言限制,这是hessian里面的一段源码

     try {
      Class<?> unsafe = Class.forName("sun.misc.Unsafe");
      Field theUnsafe = null;
      for (Field field : unsafe.getDeclaredFields()) {
        if (field.getName().equals("theUnsafe"))
          theUnsafe = field;
      }

      if (theUnsafe != null) {
        theUnsafe.setAccessible(true);
        _unsafe = (Unsafe) theUnsafe.get(null);
      }

      isEnabled = _unsafe != null;

      String unsafeProp = System.getProperty("com.caucho.hessian.unsafe");

      if ("false".equals(unsafeProp))
        isEnabled = false;
    } catch (Throwable e) {
      log.log(Level.FINER, e.toString(), e);
    }

这个是一段取一个类的私有对象的方法,通过Field类反射就可以得到私有对象,下面是一段赋值的代码

    @SuppressWarnings("restriction")
    StringFieldDeserializer(Field field)
    {
      _field = field;
      _offset = _unsafe.objectFieldOffset(_field);
    }

    @SuppressWarnings("restriction")
    void deserialize(AbstractHessianInput in, Object obj)
      throws IOException
    {
      String value = null;
     
      try {
        value = in.readString();

        _unsafe.putObject(obj, _offset, value);
      } catch (Exception e) {
        logDeserializeError(_field, obj, value, e);
      }
    }

这个是字符串属性的反序列化的代码,通过unsafe类可以得到该field的一个偏移量数据,然后通过偏移量给该field指向的对象赋值,这样就解释为什么没有set方法他也能给对象赋值,这种方式有点类是C语言里面的memset方法,知道一个地址或者指针以后,就可以对该地址存放一定类型的数据

猜你喜欢

转载自lishidi.iteye.com/blog/2026501