JDK 1.7 java.io 源码学习之ObjectInputStream和ObjectOutputStream
来源:互联网 发布:sql数据库软件下载 编辑:程序博客网 时间:2024/05/16 07:38
上一篇Serializable接口,描述了序列化和反序列化机制,其操作均是基于ObjectInputStream和ObjectOutputStream。
根据ObjectInputStream和ObjectOutputStrema类结构,需先了解两个接口:
DataInput和DataOutput
DataInput和DataOutput 用于从字节流中读取/写入Java基本类型数据或UTF编码的字符串,比较特殊的是,到达流末尾时通过抛出EOFException的方式来表示的
ObjectInput和ObjectOutput分别扩展了DataInput和DataOutput:
ObjectInput扩展了DataInput,使其支持读取对象,并缓存到一个字节数组中
ObjectOutput扩展了DataOutpu,使其可以直接将对象写入流,货主写入字节数组中
ObjectInputStream和ObjectOutputStream是比较复杂,这次主要是学习其在序列化和反序列化上的使用,以及通过readObject和writeObject实现自定义序列化的原理。
在实例化ObjectInputStream和ObjectOutputStream时,均是通过其有参构造函数实例化,传递一个FileInputStream或FileOutputStream对象。
ObjectInputStream的readObject方法:
public final Object readObject() throws IOException, ClassNotFoundException { if(enableOverrid) { return readObjectOverride(); } int outerHandle = passHandle; try { Object obj = readObject0(false); handles.markDependency(outerHandle, passHandle); ClassNotFoundException ex = handles.lookupException(passHandle); if (ex != null) { throw ex; } if (depth == 0) { vlist.doCallback(); } return obj; } finally { passHandle = outerHandle; if (closed && depth == 0) { clear(); } }}
readObject方法是final的,表示不可被Override,但是其已经通过enableOverrid标记实现了扩展,若想自定义实现,可以Override这个方法:
protected Object readObjectOverride() throws IOException, ClassNotFoundException { return null;}
该方式非常精妙,从另一种角度,实现了final修饰的方法的Override!而且将真正的处理方法封装到readObject0中
readObject方法核心的就是调用了readObject0方法:
try { switch (tc) { case TC_NULL: return readNull(); case TC_REFERENCE: return readHandle(unshared); case TC_CLASS: return readClass(unshared); case TC_CLASSDESC: case TC_PROXYCLASSDESC: return readClassDesc(unshared); case TC_STRING: case TC_LONGSTRING: return checkResolve(readString(unshared)); case TC_ARRAY: return checkResolve(readArray(unshared)); case TC_ENUM: return checkResolve(readEnum(unshared)); case TC_OBJECT: return checkResolve(readOrdinaryObject(unshared)); case TC_EXCEPTION: IOException ex = readFatalException(); throw new WriteAbortedException("writing aborted", ex); case TC_BLOCKDATA: case TC_BLOCKDATALONG: if (oldMode) { bin.setBlockDataMode(true); bin.peek(); // force header read throw new OptionalDataException( bin.currentBlockRemaining()); } else { throw new StreamCorruptedException( "unexpected block data"); } case TC_ENDBLOCKDATA: if (oldMode) { throw new OptionalDataException(true); } else { throw new StreamCorruptedException( "unexpected end of block data"); } default: throw new StreamCorruptedException( String.format("invalid type code: %02X", tc)); } } finally { depth--; bin.setBlockDataMode(oldMode);}
很明显的就是不同类型的调用不同的处理方法,这边主要看Object类型的:
checkResolve(readOrdinaryObject(unshared))
private Object readOrdinaryObject(boolean unshared) throws IOException { if (bin.readByte() != TC_OBJECT) { throw new InternalError(); } ObjectStreamClass desc = readClassDesc(false); desc.checkDeserialize(); Class<?> cl = desc.forClass(); if (cl == String.class || cl == Class.class || cl == ObjectStreamClass.class) { throw new InvalidClassException("invalid class descriptor"); } Object obj; try { obj = desc.isInstantiable() ? desc.newInstance() : null; } catch (Exception ex) { throw (IOException) new InvalidClassException( desc.forClass().getName(), "unable to create instance").initCause(ex); } passHandle = handles.assign(unshared ? unsharedMarker : obj); ClassNotFoundException resolveEx = desc.getResolveException(); if (resolveEx != null) { handles.markException(passHandle, resolveEx); } if (desc.isExternalizable()) { readExternalData((Externalizable) obj, desc); } else { readSerialData(obj, desc); } handles.finish(passHandle); if (obj != null && handles.lookupException(passHandle) == null && desc.hasReadResolveMethod()) { Object rep = desc.invokeReadResolve(obj); if (unshared && rep.getClass().isArray()) { rep = cloneArray(rep); } if (rep != obj) { handles.setObject(passHandle, obj = rep); } } return obj; }
里面这两句表示了不同的处理方式:
if (desc.isExternalizable()) { readExternalData((Externalizable) obj, desc);} else { readSerialData(obj, desc);}
即实现Serializable接口的调用readSerialData(obj, desc),实现Externalizable接口的调用readExternalData((Externalizable) obj, desc),以readSerialData为例:
private void readSerialData(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 (slots[i].hasData) { if (obj != null && slotDesc.hasReadObjectMethod() && handles.lookupException(passHandle) == null) { SerialCallbackContext oldContext = curContext; try { curContext = new SerialCallbackContext(obj, slotDesc); bin.setBlockDataMode(true); slotDesc.invokeReadObject(obj, this); } catch (ClassNotFoundException ex) { /* * In most cases, the handle table has already * propagated a CNFException to passHandle at this * point; this mark call is included to address cases * where the custom readObject method has cons'ed and * thrown a new CNFException of its own. */ handles.markException(passHandle, ex); } finally { curContext.setUsed(); curContext = oldContext; } /* * defaultDataEnd may have been set indirectly by custom * readObject() method when calling defaultReadObject() or * readFields(); clear it to restore normal read behavior. */ defaultDataEnd = false; } else { defaultReadFields(obj, slotDesc); } if (slotDesc.hasWriteObjectData()) { skipCustomData(); } else { bin.setBlockDataMode(false); } } else { if (obj != null && slotDesc.hasReadObjectNoDataMethod() && handles.lookupException(passHandle) == null) { slotDesc.invokeReadObjectNoData(obj); } } } }
里面进行了判断,slotDesc.hasReadObjectMethod即类里面有如果含有ReadObjectMethod,最终是执行了slotDesc.invokeReadObject(obj, this)。而invokeReadObject即通过反射的方式调用了该方法:
void invokeReadObject(Object obj, ObjectInputStream in) throws ClassNotFoundException, IOException, UnsupportedOperationException { if (readObjectMethod != null) { try { readObjectMethod.invoke(obj, new Object[]{ in }); } catch (InvocationTargetException ex) { Throwable th = ex.getTargetException(); if (th instanceof ClassNotFoundException) { throw (ClassNotFoundException) th; } else if (th instanceof IOException) { throw (IOException) th; } else { throwMiscException(th); } } catch (IllegalAccessException ex) { // should not occur, as access checks have been suppressed throw new InternalError(); } } else { throw new UnsupportedOperationException(); } }
invoke方法即是通过反射机制调用,故readObject方法private也是可以的,而且用private修饰以后,还能防止子类Override
ObjectOutputStream 与ObjectInputStream类似:
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; }}
writeObject也支持通过enableOverride方式扩展,被Override,也是调用的writeObject0方法,writeObject0方法里也有一个条件判断语句:
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) { writeOrdinaryObject(obj, desc, unshared);} else { if (extendedDebugInfo) { throw new NotSerializableException( cl.getName() + "\n" + debugInfoStack.toString()); } else { throw new NotSerializableException(cl.getName()); }}
也是根据类型调用不同的处理方法,以实现Serializable接口的为例:
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(); } } }
也是根据Serializable和Externalizable接口的不同调用不同的方法,具体就不贴出源码了
看的比较粗糙,后面继续完善
- JDK 1.7 java.io 源码学习之ObjectInputStream和ObjectOutputStream
- Java IO ObjectInputStream和ObjectOutputStream
- java io系列05之 ObjectInputStream 和 ObjectOutputStream
- java io系列05之 ObjectInputStream 和 ObjectOutputStream
- Java IO - ObjectInputStream&ObjectOutputStream
- Java IO : ObjectInputStream、ObjectOutputStream
- Java之IO(四)ObjectInputStream、ObjectOutputStream
- JAVA IO系列----ObjectInputStream和ObjectOutputStream类
- JAVA IO系列----ObjectInputStream和ObjectOutputStream类
- JAVA IO系列----ObjectInputStream和ObjectOutputStream类
- JAVA IO系列----ObjectInputStream和ObjectOutputStream类
- Java的IO流--ObjectInputStream和ObjectOutputStream
- Java ObjectInputStream 和 ObjectOutputStream
- 22.Java IO: ObjectInputStream && ObjectOutputStream
- java.io.ObjectOutputStream.putFields()和java.io.ObjectInputStream. readFields()
- java语言编程IO流之对象序列化和ObjectInputStream与ObjectOutputStream
- Java IO之对象的序列化、ObjectInputStream和ObjectOutputStream类
- Java-IO之对象输入流输出流(ObjectInputStream和ObjectOutputStream)
- 了解JavaScript的执行上下文
- bzoj 3456: 城市规划 (NTT+多项式求逆)
- 基于@Aspect的AOP配置
- 全新的福昕JavaScript PDF阅读器
- php开发笔记(四)php数据类型及转换
- JDK 1.7 java.io 源码学习之ObjectInputStream和ObjectOutputStream
- C#认识/理解/运用 StreamReader,StreamWriter,StringReader,StreamWriter
- QQ在线客服代码(不需要加好友即可发起临时会话)
- Swift与OC混编
- 聚火群控系统
- Android基础1
- 设备物理像素(设备像素) 设备逻辑像素(设备独立像素) 代码CSS像素 设备像素比 viewport深入理解
- 小型商城项目知识点汇总
- React组件化开发之页面构建、数据流向