ObjectInputStream 和 ObjectOutputStream 都是和对象 Serializable 有关。
writeObject 的过程 原生数据类型的序列化 创建 ObjectOutputStream 的过程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 public  ObjectOutputStream (OutputStream out)  throws  IOException  {    verifySubclass(); 	 	     bout = new  BlockDataOutputStream(out);     handles = new  HandleTable(10 , (float ) 3.00 );     subs = new  ReplaceTable(10 , (float ) 3.00 );     enableOverride = false ; 	     writeStreamHeader(); 	 	 	 	     bout.setBlockDataMode(true );     if  (extendedDebugInfo) {         debugInfoStack = new  DebugTraceInfoStack();     } else  {         debugInfoStack = null ;     } } void  drain ()  throws  IOException  {    if  (pos == 0 ) {         return ;     }     if  (blkmode) {         writeBlockHeader(pos);     }     out.write(buf, 0 , pos);     pos = 0 ; } 
 
BlockDataOutputStream 在什么时候会形成一个 data block.
在 drain 方法中,如果 当前是 块模式,则调用 writeBlockHeader 生成一个数据块头。
1 2 3 4 5 6 7 8 9 10 11 void  drain ()  throws  IOException  {    if  (pos == 0 ) {         return ;     }     if  (blkmode) { 		         writeBlockHeader(pos);     }     out.write(buf, 0 , pos);     pos = 0 ; } 
 
BlockDataOutputStream 的 blkmode 状态默认 false, 表示这个流是 关闭块模式。块模式表示的是 可以向这个流中写入数据,写入的数据默认存储在 buffer 中,当数据最终写入到 buffer 之前,会在这个前面加一个 BlockHeader。
ObjectOutputStream 内部有一个 BlockDataOutputStream 这个对象中拥有缓冲区,流的所有写入操作都先写入到这个对象的缓冲区中,
此时是写到,缓冲区的。 writeStreamHeader 写入流的 STREAM_MAGIC 和 STREAM_VERSION 共 4 个字节。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ObjectOutputStream oos = new  ObjectOutputStream(new  FileOutputStream("data" )); oos.writeInt(9999 ); oos.close();          STREAM_VERSION block_size                ↓            ↓           ↓_________↓    ↓____↓ +----+----+----+----+----+----+----+----+----+----+ | AC | ED | 00  | 05  | 77  | 04  | 00  | 00  | 27  | 0f  | +----+----+----+----+----+----+----+----+----+----+ ↑_________↑         ↑____↑    ↑___________________↑      ↑                 ↑                ↑ STREAM_MAGIC     TC_BLOCKDATA          data 其中 data 存储的字节序是:大端。 并且 data 区域,并不维护,数据类型,数据数据的维护,由代码来维护,代码当然知道,写入的数据类型是什么。 
 
对象类型的序列化 ObjectStreamClass
ObjectOutputStream.writeObject0
写入一个对象:
writeOrdinaryObject
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 private  void  writeObject0 (Object obj, boolean  unshared)  throws  IOException {	 	Class cl = obj.getClass();     ObjectStreamClass desc; 	 	     desc = ObjectStreamClass.lookup(cl, true ); 	 	writeOrdinaryObject(obj, desc, unshared); } 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(); 	             bout.writeByte(TC_OBJECT); 		         writeClassDesc(desc, false );         handles.assign(unshared ? null  : obj);         if  (desc.isExternalizable() && !desc.isProxy()) {             writeExternalData((Externalizable) obj);         } else  { 			             writeSerialData(obj, desc);         }     } finally  {         if  (extendedDebugInfo) {             debugInfoStack.pop();         }     } } private  void  writeNonProxyDesc (ObjectStreamClass desc, boolean  unshared)     throws  IOException  {    bout.writeByte(TC_CLASSDESC);     handles.assign(unshared ? null  : desc);     if  (protocol == PROTOCOL_VERSION_1) {                  desc.writeNonProxy(this );     } else  { 		         writeClassDescriptor(desc);     }     Class cl = desc.forClass();     bout.setBlockDataMode(true );     if  (isCustomSubclass()) {         ReflectUtil.checkPackageAccess(cl);     }     annotateClass(cl);     bout.setBlockDataMode(false ); 	     bout.writeByte(TC_ENDBLOCKDATA); 	 	     writeClassDesc(desc.getSuperDesc(), false ); } void  writeNonProxy (ObjectOutputStream out)  throws  IOException  {	 	     out.writeUTF(name); 	     out.writeLong(getSerialVersionUID());     byte  flags = 0 ;     if  (externalizable) {         flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;         int  protocol = out.getProtocolVersion();         if  (protocol != ObjectStreamConstants.PROTOCOL_VERSION_1) {             flags |= ObjectStreamConstants.SC_BLOCK_DATA;         }     } else  if  (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);     for  (int  i = 0 ; i < fields.length; i++) {         ObjectStreamField f = fields[i]; 		         out.writeByte(f.getTypeCode());          		out.writeUTF(f.getName());         if  (!f.isPrimitive()) { 			             out.writeTypeString(f.getTypeString());         }     } } 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()) { 			 			             PutFieldImpl oldPut = curPut;             curPut = null ;             SerialCallbackContext oldContext = curContext;             if  (extendedDebugInfo) {                 debugInfoStack.push(                     "custom writeObject data (class \""  +                     slotDesc.getName() + "\")" );             }             try  {                 curContext = new  SerialCallbackContext(obj, slotDesc);                 bout.setBlockDataMode(true ); 				 				                 slotDesc.invokeWriteObject(obj, this );                 bout.setBlockDataMode(false );                 bout.writeByte(TC_ENDBLOCKDATA);             } finally  {                 curContext.setUsed();                 curContext = oldContext;                 if  (extendedDebugInfo) {                     debugInfoStack.pop();                 }             }             curPut = oldPut;         } else  { 			 			 			 			 			 			             defaultWriteFields(obj, slotDesc);         }     } } 
 
同理,对于 readObject 方法的调用机制,也是如此,并且,如果 一个 Serializable 提供了 writeObject 方法,则其就应该提供 readObject 方法。这两个方法的签名是:
1 2 3 4 private  void  readObject (java.io.ObjectInputStream stream)      throws  IOException, ClassNotFoundException ;private  void  writeObject (java.io.ObjectOutputStream stream)      throws  IOException 
 
ObjectStreamClass 的构造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 private  ObjectStreamClass (final  Class<?> cl)   {    serializable = Serializable.class.isAssignableFrom(cl);     externalizable = Externalizable.class.isAssignableFrom(cl);     Class<?> superCl = cl.getSuperclass(); 	 	     superDesc = (superCl != null ) ? lookup(superCl, false ) : null ;     if  (serializable) {         AccessController.doPrivileged(new  PrivilegedAction<Void>() {             public  Void run ()   {                  				 				fields = getSerialFields(cl); 				 				 				 				                 if  (externalizable) {                     cons = getExternalizableConstructor(cl);                 } else  {                     cons = getSerializableConstructor(cl);                     writeObjectMethod = getPrivateMethod(cl, "writeObject" ,                         new  Class<?>[] { ObjectOutputStream.class },                         Void.TYPE);                     readObjectMethod = getPrivateMethod(cl, "readObject" ,                         new  Class<?>[] { ObjectInputStream.class },                         Void.TYPE);                     readObjectNoDataMethod = getPrivateMethod(                         cl, "readObjectNoData" , null , Void.TYPE);                     hasWriteObjectData = (writeObjectMethod != null );                 }                 writeReplaceMethod = getInheritableMethod(                     cl, "writeReplace" , null , Object.class);                 readResolveMethod = getInheritableMethod(                     cl, "readResolve" , null , Object.class);                 return  null ;             }         });     } 	 } 
 
所以写入对象数据的过程,如下:
TC_OBJECT 表示一个对象 
写入对象的类描述:例如类名,类中的字段名称,字段类型 
写入对象数据,如果对象有 writeObject ,调用 writeObject 写入数据 
如果对象没有 writeObject 方法,则调用 defaultWriteFields 将所有 non-static,non-transient 字段写入
 其写入过程: 如果当前字段是原生数据类型,则直接写入,否则,进入递归调用,转到步骤 1 开始写入这个对象字段。直到当前对象的所有字段写完,返回
 
写 superClass 的数据,重复上面的步骤
 
直到 superClass 到根类 Object 类。