首页 电脑 电脑学堂 查看内容

java的序列化机制原理分析

2012-6-4 17:35 588 0

摘要: 我们查看下ObjectOutputStream的writeObject方法 [java]   //final方法,不允许子类覆盖   ...
关键词: nbsp desc obj unshared ObjectStreamClas class IOException 对象 Object bout

我们查看下ObjectOutputStream的writeObject方法 [java]   //final方法,不允许子类覆盖     public final void writeObject(Object obj) throws IOException {         if (enableOverride) { //如果开启允许序列化被重写             writeObjectOverride(obj); //调用子类的序列化重写方法             return;         }         try {             writeObject0(obj, false);//调用默认的序列化过程         } catch (IOException ex) {             if (depth == 0) {                 writeFatalException(ex);             }             throw ex;         }     }  如果要自定义这个序列化过程,则可以写一个子类,集成ObjectOutputStream,然后覆盖其两个方法[java]protected ObjectOutputStream() throws IOException, SecurityException {      SecurityManager sm = System.getSecurityManager();      if (sm != null) {          sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);      }      bout = null;      handles = null;      subs = null;      enableOverride = true;      debugInfoStack = null;  } protected void writeObjectOverride(Object obj) throws IOException {  }  我们再看下具体的writeObject0方法:[java]private void writeObject0(Object obj, boolean unshared)          throws IOException      {         boolean oldMode = bout.setBlockDataMode(false);         depth++;         try {             // 先对obj实例的类信息进行序列化,             int h;             if ((obj = subs.lookup(obj)) == null) {                 writeNull();                 return;             } else if (!unshared && (h = handles.lookup(obj)) != -1) {//可以自定义class类信息的序列化handler                 writeHandle(h);                 return;             } else if (obj instanceof Class) { //类信息序列化                 writeClass((Class) obj, unshared);                 return;             } else if (obj instanceof ObjectStreamClass) { //类信息序列化,此时还包括serialVersionUID                 writeClassDesc((ObjectStreamClass) obj, unshared);                 return;             }                          // check for replacement object             //这里还可以对序列化的类进行替换序列化             Object orig = obj;             Class cl = obj.getClass();             ObjectStreamClass desc;             for (;;) {                 // REMIND: skip this check for strings/arrays?                 Class repCl;                 desc = ObjectStreamClass.lookup(cl, true);                 if (!desc.hasWriteReplaceMethod() ||                     (obj = desc.invokeWriteReplace(obj)) == null ||                     (repCl = obj.getClass()) == cl)                 {                     break;                 }                 cl = repCl;             }             if (enableReplace) {                 Object rep = replaceObject(obj);                 if (rep != obj && rep != null) {                     cl = rep.getClass();                     desc = ObjectStreamClass.lookup(cl, true);                 }                 obj = rep;             }              // if object replaced, run through original checks a second time             //如果类信息被替换过,则需要进行第二次处理             if (obj != orig) {                 subs.assign(orig, obj);                 if (obj == null) {                     writeNull();                     return;                 } else if (!unshared && (h = handles.lookup(obj)) != -1) {                     writeHandle(h);                     return;                 } else if (obj instanceof Class) {                     writeClass((Class) obj, unshared);                     return;                 } else if (obj instanceof ObjectStreamClass) {                     writeClassDesc((ObjectStreamClass) obj, unshared);                     return;                 }             }              // remaining cases             //写入类实例对象的数据,第一次总是在此执行             if (obj instanceof String) {                 writeString((String) obj, unshared);             } else if (cl.isArray()) {                 writeArray(obj, desc, unshared);             } else if (obj instanceof Enum) {                 writeEnum((Enum) obj, desc, unshared);             } else if (obj instanceof Serializable) { //我们的bean需要实现Serializable接口,才能进行序列化                 writeOrdinaryObject(obj, desc, unshared);             } else {                 if (extendedDebugInfo) {                     throw new NotSerializableException(                         cl.getName() + "\n" + debugInfoStack.toString());                 } else {                     throw new NotSerializableException(cl.getName());                 }                 }         } finally {             depth--;             bout.setBlockDataMode(oldMode);         }     }  我们先简单的看下如果是一个String,如何做这个序列化的过程:[java]private void writeString(String str, boolean unshared) throws IOException {        handles.assign(unshared ? null : str);         long utflen = bout.getUTFLength(str);        if (utflen <= 0xFFFF) {            bout.writeByte(TC_STRING);            bout.writeUTF(str, utflen);        } else {            bout.writeByte(TC_LONGSTRING);            bout.writeLongUTF(str, utflen);        }    }  bout的writeUTF方法:[java]void writeUTF(String s, long utflen) throws IOException {             if (utflen > 0xFFFFL) {                 throw new UTFDataFormatException();             }             writeShort((int) utflen); //先写入长度,             if (utflen == (long) s.length()) {                 writeBytes(s); //然后写入字节流             } else {                 writeUTFBody(s);             }         }  很简单,就是写入一个字符串的一个字节的标示符,然后写入字符串的字节流。     那么再看看writeOrdinaryObject(obj, desc, unshared);如何对一个bean进行序列化 [java]private void writeOrdinaryObject(Object obj,                                       ObjectStreamClass desc,                                       boolean unshared)          throws IOException      {         if (extendedDebugInfo) {             debugInfoStack.push(                 (depth == 1 ? "root " : "") + "object (class \"" +                  obj.getClass().getName() + "\", " + obj.toString() + ")");         }         try {             desc.checkSerialize(); //检查下是否可以进行序列化,比如socket对象之类的,如果对象无法进行序列化,则抛出异常。              bout.writeByte(TC_OBJECT); //先写入一个字节的类对象的标示符             writeClassDesc(desc, false); //序列化对象的class类信息 www.2cto.com              handles.assign(unshared ? null : obj); //保存类的seariableID跟对象的映射关系             if (desc.isExternalizable() && !desc.isProxy()) { //如果我们自定义了对象的序列化过程,则调用对象的writeExternalData方法。如果实现Externalizable                                                               //    /** true if represented class implements Externalizable */                                                               // private boolean externalizable;                 writeExternalData((Externalizable) obj);             } else {                 writeSerialData(obj, desc); //否则调用默认的序列化方法             }         } finally {                 if (extendedDebugInfo) {                 debugInfoStack.pop();             }           }     }  然后我们先看看writeClassDesc(desc, false)的实现:[java]private void writeClassDesc(ObjectStreamClass desc, boolean unshared)        throws IOException    {       int handle;       if (desc == null) {           writeNull();       } else if (!unshared && (handle = handles.lookup(desc)) != -1) {           writeHandle(handle);       } else if (desc.isProxy()) { //如果是proxy对象,则调用该序列化机制 ,isProxy的判断          //isProxy = Proxy.isProxyClass(cl); Returns true if and only if the specified class was dynamically generated to be a proxy class using the getProxyClass method or the newProxyInstance method.            writeProxyDesc(desc, unshared);       } else {           writeNonProxyDesc(desc, unshared);       }   }      /**   * Writes class descriptor representing a dynamic proxy class to stream.   */   private void writeProxyDesc(ObjectStreamClass desc, boolean unshared)        throws IOException    {       bout.writeByte(TC_PROXYCLASSDESC); //写入代理对象的标示符       handles.assign(unshared ? null : desc);        Class cl = desc.forClass();       Class[] ifaces = cl.getInterfaces(); //如果是proxy对象,则写入对象的interfaces的名称       bout.writeInt(ifaces.length); //先写入interface个数       for (int i = 0; i < ifaces.length; i++) {           bout.writeUTF(ifaces[i].getName()); //再写入每个interface的名称       }              bout.setBlockDataMode(true);       annotateProxyClass(cl);       bout.setBlockDataMode(false);       bout.writeByte(TC_ENDBLOCKDATA); //结束标签              writeClassDesc(desc.getSuperDesc(), false);//递归写入父类的序列化信息,因为java是单继承,   }      /**   * Writes class descriptor representing a standard (i.e., not a dynamic   * proxy) class to stream.   */   private void writeNonProxyDesc(ObjectStreamClass desc, boolean unshared)        throws IOException    {       bout.writeByte(TC_CLASSDESC);//写入class对象的标示符       handles.assign(unshared ? null : desc);              if (protocol == PROTOCOL_VERSION_1) { //如果非代理类对象的具体class信息,查看下面的方法           // do not invoke class descriptor write hook with old protocol           desc.writeNonProxy(this);       } else {           writeClassDescriptor(desc);        }              Class cl = desc.forClass();       bout.setBlockDataMode(true);       annotateClass(cl);       bout.setBlockDataMode(false);       bout.writeByte(TC_ENDBLOCKDATA);              writeClassDesc(desc.getSuperDesc(), false);//递归写入父类的序列化信息,因为java是单继承,   }  writeClassDescriptor(desc)方法:[java]       throws IOException    {        desc.writeNonProxy(this);    }  void writeNonProxy(ObjectOutputStream out) throws IOException {        out.writeUTF(name);//写入类的名称        out.writeLong(getSerialVersionUID());//写入类的SerialVersionUID         byte flags = 0;        if (externalizable) {//是否实现externalizable接口            flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;            int protocol = out.getProtocolVersion();            if (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) {                flags |= ObjectStreamConstants.SC_BLOCK_DATA;            }        } else if (serializable) {//是否实现serializable接口            flags |= ObjectStreamConstants.SC_SERIALIZABLE;        }        if (hasWriteObjectData) {//是否有自定义的重写序列化方法            flags |= ObjectStreamConstants.SC_WRITE_METHOD;        }        if (isEnum) {            flags |= ObjectStreamConstants.SC_ENUM;//是否是枚举        }        out.writeByte(flags);                out.writeShort(fields.length); //遍历写入各个类的各个field字段类型名称等信息        for (int i = 0; i < fields.length; i++) {            ObjectStreamField f = fields[i];            out.writeByte(f.getTypeCode()); //typecode参考ObjectStreamField.java类            out.writeUTF(f.getName());            if (!f.isPrimitive()) {                out.writeTypeString(f.getTypeString());            }        }    }  typecode:[java]case 'Z': type = Boolean.TYPE; break; case 'B': type = Byte.TYPE; break; case 'C': type = Character.TYPE; break; case 'S': type = Short.TYPE; break; case 'I': type = Integer.TYPE; break; case 'J': type = Long.TYPE; break; case 'F': type = Float.TYPE; break; case 'D': type = Double.TYPE; break; case 'L': case '[': type = Object.class; break;  至此,对象obj的class相关信息已经全部写入。然后我们再查看具体写入obj数据的过程 [java]private void writeSerialData(Object obj, ObjectStreamClass desc)         throws IOException     {        ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();        for (int i = 0; i < slots.length; i++) {            ObjectStreamClass slotDesc = slots[i].desc;            if (slotDesc.hasWriteObjectMethod()) { //Returns true if represented class is serializable (but not externalizable) and defines a conformant writeObject method. Otherwise, returns false.                Object oldObj = curObj;                ObjectStreamClass oldDesc = curDesc;                PutFieldImpl oldPut = curPut;                curObj = obj;                curDesc = slotDesc;                curPut = null;                 if (extendedDebugInfo) {                    debugInfoStack.push(                        "custom writeObject data (class \"" +                         slotDesc.getName() + "\")");                }                        try {                    bout.setBlockDataMode(true);                    slotDesc.invokeWriteObject(obj, this);                    bout.setBlockDataMode(false);                    bout.writeByte(TC_ENDBLOCKDATA);                } finally {                    if (extendedDebugInfo) {                        debugInfoStack.pop();                    }                        }                  curObj = oldObj;                curDesc = oldDesc;                curPut = oldPut;            } else {                defaultWriteFields(obj, slotDesc); //写入对象的字段数据            }        }    }    private void defaultWriteFields(Object obj, ObjectStreamClass desc)        throws IOException    {        // REMIND: perform conservative isInstance check here?        desc.checkDefaultSerialize();         int primDataSize = desc.getPrimDataSize(); //先写入private field的数据        if (primVals == null || primVals.length < primDataSize) {            primVals = new byte[primDataSize];        }        desc.getPrimFieldValues(obj, primVals);        bout.write(primVals, 0, primDataSize, false);                ObjectStreamField[] fields = desc.getFields(false);        Object[] objVals = new Object[desc.getNumObjFields()];        int numPrimFields = fields.length - objVals.length;        desc.getObjFieldValues(obj, objVals);        for (int i = 0; i < objVals.length; i++) { //写入非private的数据            if (extendedDebugInfo) {                debugInfoStack.push(                    "field (class \"" + desc.getName() + "\", name: \"" +                     fields[numPrimFields + i].getName() + "\", type: \"" +                     fields[numPrimFields + i].getType() + "\")");            }                    try {                writeObject0(objVals[i],                              fields[numPrimFields + i].isUnshared()); //递归调用writeObject0写入每个field的数据            } finally {                if (extendedDebugInfo) {                    debugInfoStack.pop();                }                 }                }    }  当然ObjectInputStream也类似。     摘自 zhwj的专栏
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部