- 浏览: 980100 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
Java Socket编程实例:http://donald-draper.iteye.com/blog/2356695
java Socket读写缓存区Writer和Reader:http://donald-draper.iteye.com/blog/2356885
Java NIO ByteBuffer详解:http://donald-draper.iteye.com/blog/2357084
Java序列化与反序列化实例分析:http://donald-draper.iteye.com/blog/2357515
Java序列化与反序列化详解:http://donald-draper.iteye.com/blog/2357540
在上一篇文章中,我们讲了java序列化的过程,今天有时间,我们来看一下反序列化过程,在看之前先回顾一下,序列
化:
ObjectOutputStream的构造,主要是构造对象,对象输出流BlockDataOutputStream
,BlockDataOutputStream主要是写序列化的流数据,BlockDataOutputStream中有一个存放序列化数据的缓存区,头部数据缓冲区,原始类型数据缓冲区,其中关联一个原始类型输出流DataOutputStream,(DataOutput)主要用于写原始类型数据,int,float,String,double等;同时写流版本号和流魔数。然后,写类流对象描述,主要写类名,序列版本号,类型,属性个数,属性描述;然后写对象属性值,当对象父接口是Serializable,如果Serializable实现了WriteObject方法,则直接调用WriteObject序列化属性值,否则,通过反射获取对象属性的值,写到缓存中,如果对象父接口Externalizable,则直接调用对象writeExternal方法序列化对象。
下面我们来看反序列化过程:
从下面这段代码看起:
先看一下构造:
再来看BlockDataInputStream
//PeekInputStream,主要是从缓冲中去取字节流数据
从上面可以看出,ObjectInputStream初始化主要是,构造BlockDataInputStream,
从缓冲中读取数据,然后读取流魔数与版本号;
再来关键反序列化过程:
//从缓冲中,反序列化对象
//根据反序列化对象类型,够到对象
反序列化Object对象
先看
//获取对象类描述信息
来看读取对象描述信息
//读取对象描述信息
//ObjectStreamClass
//ObjectStreamField
//根据属性类型,初始化属性读取的缓存位置
回到readNonProxyDesc的方法这一句:
//加载类
//ObjectInputStream
回到readNonProxyDesc的方法这一句:
//ObjectStreamClass
回到readOrdinaryObject的这一句
//加载Class
回到readOrdinaryObject的这一句
//如果是Externalizable
先看
再来看
//否则读取属性
//ObjectStreamClass
回到readOrdinaryObject的这一句
//如果对象有readResolve,则调用readResolve方法
总结:
ObjectInputStream初始化主要是,构造BlockDataInputStream,从缓冲中读取数据,然后读取流魔数与版本号;然后从缓冲中读取对象流描述信息,包括类型,属性名,及每个属性对应的读取位置;在加载流对象描述信息类;如果是Externalizable,则调用对象的readExternal的方法,如果是Serializable,有ReadObject,则通过反射调用ReadObject方法,没有从缓冲中读取属性数据,并给属性赋值;如果对象中有readResolve方法,则调用readResolve,并返回。
来看一个readint
//ObjectInputStream
//BlockDataInputStream
//Double
//ObjectStreamConstants
java Socket读写缓存区Writer和Reader:http://donald-draper.iteye.com/blog/2356885
Java NIO ByteBuffer详解:http://donald-draper.iteye.com/blog/2357084
Java序列化与反序列化实例分析:http://donald-draper.iteye.com/blog/2357515
Java序列化与反序列化详解:http://donald-draper.iteye.com/blog/2357540
在上一篇文章中,我们讲了java序列化的过程,今天有时间,我们来看一下反序列化过程,在看之前先回顾一下,序列
化:
ObjectOutputStream的构造,主要是构造对象,对象输出流BlockDataOutputStream
,BlockDataOutputStream主要是写序列化的流数据,BlockDataOutputStream中有一个存放序列化数据的缓存区,头部数据缓冲区,原始类型数据缓冲区,其中关联一个原始类型输出流DataOutputStream,(DataOutput)主要用于写原始类型数据,int,float,String,double等;同时写流版本号和流魔数。然后,写类流对象描述,主要写类名,序列版本号,类型,属性个数,属性描述;然后写对象属性值,当对象父接口是Serializable,如果Serializable实现了WriteObject方法,则直接调用WriteObject序列化属性值,否则,通过反射获取对象属性的值,写到缓存中,如果对象父接口Externalizable,则直接调用对象writeExternal方法序列化对象。
下面我们来看反序列化过程:
从下面这段代码看起:
ObjectInputStream objectInputStream = null; try { objectInputStream = new ObjectInputStream(inFile); } catch (IOException e) { e.printStackTrace(); } PersonX getPerson = null; try { getPerson = (PersonX) objectInputStream.readObject(); int int0 = objectInputStream.readInt(); System.out.println("=======read int after read object persion:"+int0); String str = objectInputStream.readUTF(); System.out.println("=======read UTF after read object persion and int:"+str); objectInputStream.close(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
先看一下构造:
//ObjectInputStream public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants { /** filter stream for handling block data conversion */ private final BlockDataInputStream bin;//数据输入流 /** validation callback list */ private final ValidationList vlist; /** recursion depth */ private int depth; /** whether stream is closed */ private boolean closed; /** wire handle -> obj/exception map */ private final HandleTable handles; /** scratch field for passing handle values up/down call stack */ private int passHandle = NULL_HANDLE; /** flag set when at end of field value block with no TC_ENDBLOCKDATA */ private boolean defaultDataEnd = false; /** buffer for reading primitive field values */ private byte[] primVals;//原始类型变量幻从去 /** if true, invoke readObjectOverride() instead of readObject() */ private final boolean enableOverride; /** if true, invoke resolveObject() */ private boolean enableResolve; /** * Context during upcalls to class-defined readObject methods; holds * object currently being deserialized and descriptor for current class. * Null when not during readObject upcall. */ private SerialCallbackContext curContext; public ObjectInputStream(InputStream in) throws IOException { verifySubclass(); //构造BlockDataInputStream bin = new BlockDataInputStream(in); handles = new HandleTable(10); vlist = new ValidationList(); enableOverride = false; //读取流魔数与版本号 readStreamHeader(); bin.setBlockDataMode(true); } //读取流魔数与版本号 protected void readStreamHeader() throws IOException, StreamCorruptedException { short s0 = bin.readShort(); short s1 = bin.readShort(); if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) { throw new StreamCorruptedException( String.format("invalid stream header: %04X%04X", s0, s1)); } } }
再来看BlockDataInputStream
// BlockDataInputStream private class BlockDataInputStream extends InputStream implements DataInput { /** maximum data block length */ private static final int MAX_BLOCK_SIZE = 1024; /** maximum data block header length */ private static final int MAX_HEADER_SIZE = 5; /** (tunable) length of char buffer (for reading strings) */ private static final int CHAR_BUF_SIZE = 256; /** readBlockHeader() return value indicating header read may block */ private static final int HEADER_BLOCKED = -2; /** buffer for reading general/block data */ private final byte[] buf = new byte[MAX_BLOCK_SIZE];//输入流缓存 /** buffer for reading block data headers */ private final byte[] hbuf = new byte[MAX_HEADER_SIZE];//头部缓存 /** char buffer for fast string reads */ private final char[] cbuf = new char[CHAR_BUF_SIZE];//字符缓存 /** block data mode */ private boolean blkmode = false; // block data state fields; values meaningful only when blkmode true /** current offset into buf */ private int pos = 0;//缓存读取位置 /** end offset of valid data in buf, or -1 if no more block data */ private int end = -1; /** number of bytes in current block yet to be read from stream */ private int unread = 0;//缓存中还有,多少数据未读取 /** underlying stream (wrapped in peekable filter stream) */ private final PeekInputStream in;//从缓冲中取数据辅助流 /** loopback stream (for data reads that span data blocks) */ private final DataInputStream din;//原始类型解析辅助流 /** * Creates new BlockDataInputStream on top of given underlying stream. * Block data mode is turned off by default. */ BlockDataInputStream(InputStream in) { this.in = new PeekInputStream(in); din = new DataInputStream(this); } }
//PeekInputStream,主要是从缓冲中去取字节流数据
/** * Input stream supporting single-byte peek operations. */ private static class PeekInputStream extends InputStream { /** underlying stream */ private final InputStream in; /** peeked byte */ private int peekb = -1; /** * Creates new PeekInputStream on top of given underlying stream. */ PeekInputStream(InputStream in) { this.in = in; } /** * Peeks at next byte value in stream. Similar to read(), except * that it does not consume the read value. */ int peek() throws IOException { return (peekb >= 0) ? peekb : (peekb = in.read()); } public int read() throws IOException { if (peekb >= 0) { int v = peekb; peekb = -1; return v; } else { return in.read(); } } public int read(byte[] b, int off, int len) throws IOException { if (len == 0) { return 0; } else if (peekb < 0) { return in.read(b, off, len); } else { b[off++] = (byte) peekb; len--; peekb = -1; int n = in.read(b, off, len); return (n >= 0) ? (n + 1) : 1; } } void readFully(byte[] b, int off, int len) throws IOException { int n = 0; while (n < len) { int count = read(b, off + n, len - n); if (count < 0) { throw new EOFException(); } n += count; } } public long skip(long n) throws IOException { if (n <= 0) { return 0; } int skipped = 0; if (peekb >= 0) { peekb = -1; skipped++; n--; } return skipped + skip(n); } public int available() throws IOException { return in.available() + ((peekb >= 0) ? 1 : 0); } public void close() throws IOException { in.close(); } }
从上面可以看出,ObjectInputStream初始化主要是,构造BlockDataInputStream,
从缓冲中读取数据,然后读取流魔数与版本号;
再来关键反序列化过程:
//从缓冲中,反序列化对象
public final Object readObject() throws IOException, ClassNotFoundException { if (enableOverride) { return readObjectOverride(); } // if nested read, passHandle contains handle of enclosing object int outerHandle = passHandle; try { //委托给readObject0 Object obj = readObject0(false); ... return obj; } finally { passHandle = outerHandle; if (closed && depth == 0) { clear(); } } }
//根据反序列化对象类型,够到对象
private Object readObject0(boolean unshared) throws IOException { boolean oldMode = bin.getBlockDataMode(); if (oldMode) { int remain = bin.currentBlockRemaining(); if (remain > 0) { throw new OptionalDataException(remain); } else if (defaultDataEnd) { /* * Fix for 4360508: stream is currently at the end of a field * value block written via default serialization; since there * is no terminating TC_ENDBLOCKDATA tag, simulate * end-of-custom-data behavior explicitly. */ throw new OptionalDataException(true); } bin.setBlockDataMode(false); } byte tc; //读取反序列化对象类型 while ((tc = bin.peekByte()) == TC_RESET) { bin.readByte(); handleReset(); } depth++; try { //根据反序列化对象类型,够到对象 switch (tc) { case TC_NULL: return readNull(); case TC_REFERENCE: return readHandle(unshared); case TC_CLASS: //反序列化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: //读取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对象
/** * Reads and returns "ordinary" (i.e., not a String, Class, * ObjectStreamClass, array, or enum constant) object, or null if object's * class is unresolvable (in which case a ClassNotFoundException will be * associated with object's handle). Sets passHandle to object's assigned * handle. */ private Object readOrdinaryObject(boolean unshared) throws IOException { if (bin.readByte() != TC_OBJECT) { //如果非Object对象,抛出异常 throw new InternalError(); } //获取对象类型描述信息 ObjectStreamClass desc = readClassDesc(false); desc.checkDeserialize(); //加载Class 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); } //如果是Externalizable if (desc.isExternalizable()) { readExternalData((Externalizable) obj, desc); } else { //如果是Serializable readSerialData(obj, desc); } handles.finish(passHandle); if (obj != null && handles.lookupException(passHandle) == null && desc.hasReadResolveMethod()) { //如果对象有readResolve,则调用readResolve方法 Object rep = desc.invokeReadResolve(obj); if (unshared && rep.getClass().isArray()) { rep = cloneArray(rep); } if (rep != obj) { handles.setObject(passHandle, obj = rep); } } return obj; }
先看
//获取对象类描述信息
ObjectStreamClass desc = readClassDesc(false);
private ObjectStreamClass readClassDesc(boolean unshared) throws IOException { byte tc = bin.peekByte(); switch (tc) { case TC_NULL: return (ObjectStreamClass) readNull(); case TC_REFERENCE: return (ObjectStreamClass) readHandle(unshared); case TC_PROXYCLASSDESC: //读取代理对象的信息 return readProxyDesc(unshared); case TC_CLASSDESC: //读取非代理对象的信息 return readNonProxyDesc(unshared); default: throw new StreamCorruptedException( String.format("invalid type code: %02X", tc)); } }
/** * Reads in and returns class descriptor for a class that is not a dynamic * proxy class. Sets passHandle to class descriptor's assigned handle. If * class descriptor cannot be resolved to a class in the local VM, a * ClassNotFoundException is associated with the descriptor's handle. */ private ObjectStreamClass readNonProxyDesc(boolean unshared) throws IOException { if (bin.readByte() != TC_CLASSDESC) { //非对象流描述类,则抛出异常 throw new InternalError(); } ObjectStreamClass desc = new ObjectStreamClass(); int descHandle = handles.assign(unshared ? unsharedMarker : desc); passHandle = NULL_HANDLE; ObjectStreamClass readDesc = null; try { //读取对象描述信息 readDesc = readClassDescriptor(); } catch (ClassNotFoundException ex) { throw (IOException) new InvalidClassException( "failed to read class descriptor").initCause(ex); } Class cl = null; ClassNotFoundException resolveEx = null; bin.setBlockDataMode(true); try { //先调用序列化类的resolveClass if ((cl = resolveClass(readDesc)) == null) { resolveEx = new ClassNotFoundException("null class"); } } catch (ClassNotFoundException ex) { resolveEx = ex; } //跳过非必要数据 skipCustomData(); //初始化对象 desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false)); handles.finish(descHandle); passHandle = descHandle; return desc; }
来看读取对象描述信息
//读取对象描述信息
readDesc = readClassDescriptor();
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { ObjectStreamClass desc = new ObjectStreamClass(); //委托给ObjectStreamClass的readNonProxy方法 desc.readNonProxy(this); return desc; }
//ObjectStreamClass
void readNonProxy(ObjectInputStream in) throws IOException, ClassNotFoundException { //读取类名 name = in.readUTF(); //读取类型序列号 suid = Long.valueOf(in.readLong()); isProxy = false; //读取对象序列化的方式,writeObject方法,Serializable,Externalizable,还是SC_BLOCK_DATA byte flags = in.readByte(); hasWriteObjectData = ((flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0); hasBlockExternalData = ((flags & ObjectStreamConstants.SC_BLOCK_DATA) != 0); externalizable = ((flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0); boolean sflag = ((flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0); if (externalizable && sflag) { throw new InvalidClassException( name, "serializable and externalizable flags conflict"); } serializable = externalizable || sflag; isEnum = ((flags & ObjectStreamConstants.SC_ENUM) != 0); if (isEnum && suid.longValue() != 0L) { throw new InvalidClassException(name, "enum descriptor has non-zero serialVersionUID: " + suid); } //读取对象属性个数 int numFields = in.readShort(); if (isEnum && numFields != 0) { throw new InvalidClassException(name, "enum descriptor has non-zero field count: " + numFields); } fields = (numFields > 0) ? new ObjectStreamField[numFields] : NO_FIELDS; //读取对象属性类型,及name for (int i = 0; i < numFields; i++) { //读取对象属性,类型编码 char tcode = (char) in.readByte(); //读取对象属性名 String fname = in.readUTF(); String signature = ((tcode == 'L') || (tcode == '[')) ? in.readTypeString() : new String(new char[] { tcode }); try { fields[i] = new ObjectStreamField(fname, signature, false); } catch (RuntimeException e) { throw (IOException) new InvalidClassException(name, "invalid descriptor for field " + fname).initCause(e); } } //根据属性类型,初始化属性读取的缓存位置 computeFieldOffsets(); }
//ObjectStreamField
ObjectStreamField(String name, String signature, boolean unshared) { if (name == null) { throw new NullPointerException(); } this.name = name; this.signature = signature.intern(); this.unshared = unshared; field = null; switch (signature.charAt(0)) { 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; default: throw new IllegalArgumentException("illegal signature"); } }
//根据属性类型,初始化属性读取的缓存位置
private void computeFieldOffsets() throws InvalidClassException { primDataSize = 0; numObjFields = 0; int firstObjIndex = -1; //根据属性类型,初始化属性读取的缓存位置 for (int i = 0; i < fields.length; i++) { ObjectStreamField f = fields[i]; switch (f.getTypeCode()) { //boolean,byte类型一个字节 case 'Z': case 'B': f.setOffset(primDataSize++); break; //char,short类型2个字节 case 'C': case 'S': f.setOffset(primDataSize); primDataSize += 2; break; //int,float类型4个字节 case 'I': case 'F': f.setOffset(primDataSize); primDataSize += 4; break; //long,double类型8个字节 case 'J': case 'D': f.setOffset(primDataSize); primDataSize += 8; break; case '[': case 'L': f.setOffset(numObjFields++); if (firstObjIndex == -1) { firstObjIndex = i; } break; default: throw new InternalError(); } } if (firstObjIndex != -1 && firstObjIndex + numObjFields != fields.length) { throw new InvalidClassException(name, "illegal field order"); } }
回到readNonProxyDesc的方法这一句:
//加载类
if ((cl = resolveClass(readDesc)) == null) { resolveEx = new ClassNotFoundException("null class"); }
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String name = desc.getName(); try { return Class.forName(name, false, latestUserDefinedLoader()); } catch (ClassNotFoundException ex) { //如果非class类,从原始类型Map中获取 Class<?> cl = primClasses.get(name); if (cl != null) { return cl; } else { throw ex; } } }
//ObjectInputStream
public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants { /** handle value representing null */ private static final int NULL_HANDLE = -1; /** marker for unshared objects in internal handle table */ private static final Object unsharedMarker = new Object(); /** table mapping primitive type names to corresponding class objects */ private static final HashMap<String, Class<?>> primClasses = new HashMap<>(8, 1.0F); static { primClasses.put("boolean", boolean.class); primClasses.put("byte", byte.class); primClasses.put("char", char.class); primClasses.put("short", short.class); primClasses.put("int", int.class); primClasses.put("long", long.class); primClasses.put("float", float.class); primClasses.put("double", double.class); primClasses.put("void", void.class); } } 回到readNonProxyDesc的方法这一句: skipCustomData(); /** * Skips over all block data and objects until TC_ENDBLOCKDATA is * encountered. */ private void skipCustomData() throws IOException { int oldHandle = passHandle; for (;;) { if (bin.getBlockDataMode()) { bin.skipBlockData(); bin.setBlockDataMode(false); } switch (bin.peekByte()) { case TC_BLOCKDATA: case TC_BLOCKDATALONG: bin.setBlockDataMode(true); break; case TC_ENDBLOCKDATA: bin.readByte(); passHandle = oldHandle; return; default: readObject0(false); break; } } }
回到readNonProxyDesc的方法这一句:
desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
//ObjectStreamClass
/** * Initializes class descriptor representing a non-proxy class. */ void initNonProxy(ObjectStreamClass model, Class<?> cl, ClassNotFoundException resolveEx, ObjectStreamClass superDesc) throws InvalidClassException { this.cl = cl; this.resolveEx = resolveEx; this.superDesc = superDesc; //类名 name = model.name; //序列号 suid = Long.valueOf(model.getSerialVersionUID()); isProxy = false; //是否为Enum isEnum = model.isEnum; //父接口类型serializable、externalizable serializable = model.serializable; externalizable = model.externalizable; hasBlockExternalData = model.hasBlockExternalData; //对象是否有WriteObject方法 hasWriteObjectData = model.hasWriteObjectData; //属性 fields = model.fields; //原始类型数据大小 primDataSize = model.primDataSize; //属性书量 numObjFields = model.numObjFields; if (cl != null) { localDesc = lookup(cl, true); if (localDesc.isProxy) { throw new InvalidClassException( "cannot bind non-proxy descriptor to a proxy class"); } if (isEnum != localDesc.isEnum) { throw new InvalidClassException(isEnum ? "cannot bind enum descriptor to a non-enum class" : "cannot bind non-enum descriptor to an enum class"); } if (serializable == localDesc.serializable && !cl.isArray() && suid.longValue() != localDesc.getSerialVersionUID()) { throw new InvalidClassException(localDesc.name, "local class incompatible: " + "stream classdesc serialVersionUID = " + suid + ", local class serialVersionUID = " + localDesc.getSerialVersionUID()); } if (!classNamesEqual(name, localDesc.name)) { throw new InvalidClassException(localDesc.name, "local class name incompatible with stream class " + "name \"" + name + "\""); } if (!isEnum) { if ((serializable == localDesc.serializable) && (externalizable != localDesc.externalizable)) { throw new InvalidClassException(localDesc.name, "Serializable incompatible with Externalizable"); } if ((serializable != localDesc.serializable) || (externalizable != localDesc.externalizable) || !(serializable || externalizable)) { deserializeEx = new ExceptionInfo( localDesc.name, "class invalid for deserialization"); } } cons = localDesc.cons; //初始化writeObjectMethod,readObjectMethod,readResolveMethod writeObjectMethod = localDesc.writeObjectMethod; readObjectMethod = localDesc.readObjectMethod; readObjectNoDataMethod = localDesc.readObjectNoDataMethod; writeReplaceMethod = localDesc.writeReplaceMethod; readResolveMethod = localDesc.readResolveMethod; if (deserializeEx == null) { deserializeEx = localDesc.deserializeEx; } } //获取对象属性反射器,这段我们在上一篇已将看过 fieldRefl = getReflector(fields, localDesc); // reassign to matched fields so as to reflect local unshared settings fields = fieldRefl.getFields(); } }
/** * Matches given set of serializable fields with serializable fields * described by the given local class descriptor, and returns a * FieldReflector instance capable of setting/getting values from the * subset of fields that match (non-matching fields are treated as filler, * for which get operations return default values and set operations * discard given values). Throws InvalidClassException if unresolvable * type conflicts exist between the two sets of fields. */ //从ObjectStreamClass的获取Field对应的反射器 private static FieldReflector getReflector(ObjectStreamField[] fields, ObjectStreamClass localDesc) throws InvalidClassException { // class irrelevant if no fields Class<?> cl = (localDesc != null && fields.length > 0) ? localDesc.cl : null; processQueue(Caches.reflectorsQueue, Caches.reflectors); FieldReflectorKey key = new FieldReflectorKey(cl, fields, Caches.reflectorsQueue); Reference<?> ref = Caches.reflectors.get(key); Object entry = null; if (ref != null) { entry = ref.get(); } EntryFuture future = null; if (entry == null) { EntryFuture newEntry = new EntryFuture(); Reference<?> newRef = new SoftReference<>(newEntry); do { if (ref != null) { Caches.reflectors.remove(key, ref); } ref = Caches.reflectors.putIfAbsent(key, newRef); if (ref != null) { entry = ref.get(); } } while (ref != null && entry == null); if (entry == null) { future = newEntry; } } if (entry instanceof FieldReflector) { // check common case first return (FieldReflector) entry; } else if (entry instanceof EntryFuture) { entry = ((EntryFuture) entry).get(); } else if (entry == null) { try { entry = new FieldReflector(matchFields(fields, localDesc)); } catch (Throwable th) { entry = th; } future.set(entry); Caches.reflectors.put(key, new SoftReference<Object>(entry)); } if (entry instanceof FieldReflector) { return (FieldReflector) entry; } else if (entry instanceof InvalidClassException) { throw (InvalidClassException) entry; } else if (entry instanceof RuntimeException) { throw (RuntimeException) entry; } else if (entry instanceof Error) { throw (Error) entry; } else { throw new InternalError("unexpected entry: " + entry); } }
/** * Returns list of ObjectStreamFields representing fields operated on * by this reflector. The shared/unshared values and Field objects * contained by ObjectStreamFields in the list reflect their bindings * to locally defined serializable fields. */ //ObjectStreamClass ObjectStreamField[] getFields() { return fields; }
回到readOrdinaryObject的这一句
//加载Class
Class<?> cl = desc.forClass();
//ObjectStreamClass /** * Return the class in the local VM that this version is mapped to. Null * is returned if there is no corresponding local class. * * @return the <code>Class</code> instance that this descriptor represents */ public Class<?> forClass() { return cl; }
回到readOrdinaryObject的这一句
//如果是Externalizable
if (desc.isExternalizable()) { readExternalData((Externalizable) obj, desc); } else { //如果是Serializable readSerialData(obj, desc); }
先看
readExternalData((Externalizable) obj, desc);
private void readExternalData(Externalizable obj, ObjectStreamClass desc) throws IOException { SerialCallbackContext oldContext = curContext; curContext = null; try { boolean blocked = desc.hasBlockExternalData(); if (blocked) { bin.setBlockDataMode(true); } if (obj != null) { try { //调用对象的readExternal obj.readExternal(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 readExternal * method has cons'ed and thrown a new CNFException of its * own. */ handles.markException(passHandle, ex); } } if (blocked) { skipCustomData(); } } finally { curContext = oldContext; }
再来看
readSerialData(obj, desc);
/** * Reads (or attempts to skip, if obj is null or is tagged with a * ClassNotFoundException) instance data for each serializable class of * object in stream, from superclass to subclass. Expects that passHandle * is set to obj's handle before this method is called. */ 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); //如果对象有ReadObject,则调用对象的Object方法 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); } } } }
//否则读取属性
defaultReadFields(obj, slotDesc);
/** * Reads in values of serializable fields declared by given class * descriptor. If obj is non-null, sets field values in obj. Expects that * passHandle is set to obj's handle before this method is called. */ private void defaultReadFields(Object obj, ObjectStreamClass desc) throws IOException { // REMIND: is isInstance check necessary? Class cl = desc.forClass(); if (cl != null && obj != null && !cl.isInstance(obj)) { throw new ClassCastException(); } //获取原始类型个数 int primDataSize = desc.getPrimDataSize(); if (primVals == null || primVals.length < primDataSize) { primVals = new byte[primDataSize]; } //从缓冲区,读取所有属性数据 bin.readFully(primVals, 0, primDataSize, false); if (obj != null) { //设置对象原始类型属性数据 desc.setPrimFieldValues(obj, primVals); } int objHandle = passHandle; ObjectStreamField[] fields = desc.getFields(false); Object[] objVals = new Object[desc.getNumObjFields()]; int numPrimFields = fields.length - objVals.length; //遍历所有Field,并读取属性值 for (int i = 0; i < objVals.length; i++) { ObjectStreamField f = fields[numPrimFields + i]; objVals[i] = readObject0(f.isUnshared()); if (f.getField() != null) { handles.markDependency(objHandle, passHandle); } } if (obj != null) { //设置所有属性值 desc.setObjFieldValues(obj, objVals); } passHandle = objHandle; }
//ObjectStreamClass
/** * Sets the serializable object fields of object obj using values from * array vals starting at offset 0. It is the responsibility of the caller * to ensure that obj is of the proper type if non-null. */ void setObjFieldValues(Object obj, Object[] vals) { fieldRefl.setObjFieldValues(obj, vals); } /** * Invokes the readObject method of the represented serializable class. * Throws UnsupportedOperationException if this class descriptor is not * associated with a class, or if the class is externalizable, * non-serializable or does not define readObject. */ void invokeReadObject(Object obj, ObjectInputStream in) throws ClassNotFoundException, IOException, UnsupportedOperationException { if (readObjectMethod != null) { try { readObjectMethod.invoke(obj, new Object[]{ in }); } else { throw new UnsupportedOperationException(); } }
回到readOrdinaryObject的这一句
//如果对象有readResolve,则调用readResolve方法
Object rep = desc.invokeReadResolve(obj);
//ObjectStreamClass /** * Invokes the writeReplace method of the represented serializable class and * returns the result. Throws UnsupportedOperationException if this class * descriptor is not associated with a class, or if the class is * non-serializable or does not define writeReplace. */ Object invokeWriteReplace(Object obj) throws IOException, UnsupportedOperationException { if (writeReplaceMethod != null) { try { return writeReplaceMethod.invoke(obj, (Object[]) null); } }
总结:
ObjectInputStream初始化主要是,构造BlockDataInputStream,从缓冲中读取数据,然后读取流魔数与版本号;然后从缓冲中读取对象流描述信息,包括类型,属性名,及每个属性对应的读取位置;在加载流对象描述信息类;如果是Externalizable,则调用对象的readExternal的方法,如果是Serializable,有ReadObject,则通过反射调用ReadObject方法,没有从缓冲中读取属性数据,并给属性赋值;如果对象中有readResolve方法,则调用readResolve,并返回。
来看一个readint
//ObjectInputStream
public int readInt() throws IOException { return bin.readInt(); }
//BlockDataInputStream
public int readInt() throws IOException { if (!blkmode) { pos = 0; in.readFully(buf, 0, 4); } else if (end - pos < 4) { return din.readInt(); } int v = Bits.getInt(buf, pos); pos += 4; return v; }
//Double
public final class Double extends Number implements Comparable<Double> { /** * The {@code Class} instance representing the primitive type * {@code double}. * * @since JDK1.1 */ public static final Class<Double> TYPE = (Class<Double>) Class.getPrimitiveClass("double"); }
//ObjectStreamConstants
package java.io; /** * Constants written into the Object Serialization Stream. * * @author unascribed * @since JDK 1.1 */ public interface ObjectStreamConstants { /** * Magic number that is written to the stream header. */ final static short STREAM_MAGIC = (short)0xaced; /** * Version number that is written to the stream header. */ final static short STREAM_VERSION = 5; /* Each item in the stream is preceded by a tag */ /** * First tag value. */ final static byte TC_BASE = 0x70; /** * Null object reference. */ final static byte TC_NULL = (byte)0x70; /** * Reference to an object already written into the stream. */ final static byte TC_REFERENCE = (byte)0x71; /** * new Class Descriptor. */ final static byte TC_CLASSDESC = (byte)0x72; /** * new Object. */ final static byte TC_OBJECT = (byte)0x73; /** * new String. */ final static byte TC_STRING = (byte)0x74; /** * new Array. */ final static byte TC_ARRAY = (byte)0x75; /** * Reference to Class. */ final static byte TC_CLASS = (byte)0x76; /** * Block of optional data. Byte following tag indicates number * of bytes in this block data. */ final static byte TC_BLOCKDATA = (byte)0x77; /** * End of optional block data blocks for an object. */ final static byte TC_ENDBLOCKDATA = (byte)0x78; /** * Reset stream context. All handles written into stream are reset. */ final static byte TC_RESET = (byte)0x79; /** * long Block data. The long following the tag indicates the * number of bytes in this block data. */ final static byte TC_BLOCKDATALONG= (byte)0x7A; /** * Exception during write. */ final static byte TC_EXCEPTION = (byte)0x7B; /** * Long string. */ final static byte TC_LONGSTRING = (byte)0x7C; /** * new Proxy Class Descriptor. */ final static byte TC_PROXYCLASSDESC = (byte)0x7D; /** * new Enum constant. * @since 1.5 */ final static byte TC_ENUM = (byte)0x7E; /** * Last tag value. */ final static byte TC_MAX = (byte)0x7E; /** * First wire handle to be assigned. */ final static int baseWireHandle = 0x7e0000; /******************************************************/ /* Bit masks for ObjectStreamClass flag.*/ /** * Bit mask for ObjectStreamClass flag. Indicates a Serializable class * defines its own writeObject method. */ final static byte SC_WRITE_METHOD = 0x01; /** * Bit mask for ObjectStreamClass flag. Indicates Externalizable data * written in Block Data mode. * Added for PROTOCOL_VERSION_2. * * @see #PROTOCOL_VERSION_2 * @since 1.2 */ final static byte SC_BLOCK_DATA = 0x08; /** * Bit mask for ObjectStreamClass flag. Indicates class is Serializable. */ final static byte SC_SERIALIZABLE = 0x02; /** * Bit mask for ObjectStreamClass flag. Indicates class is Externalizable. */ final static byte SC_EXTERNALIZABLE = 0x04; /** * Bit mask for ObjectStreamClass flag. Indicates class is an enum type. * @since 1.5 */ final static byte SC_ENUM = 0x10; /* *******************************************************************/ /* Security permissions */ /** * Enable substitution of one object for another during * serialization/deserialization. * * @see java.io.ObjectOutputStream#enableReplaceObject(boolean) * @see java.io.ObjectInputStream#enableResolveObject(boolean) * @since 1.2 */ final static SerializablePermission SUBSTITUTION_PERMISSION = new SerializablePermission("enableSubstitution"); /** * Enable overriding of readObject and writeObject. * * @see java.io.ObjectOutputStream#writeObjectOverride(Object) * @see java.io.ObjectInputStream#readObjectOverride() * @since 1.2 */ final static SerializablePermission SUBCLASS_IMPLEMENTATION_PERMISSION = new SerializablePermission("enableSubclassImplementation"); /** * A Stream Protocol Version. <p> * * All externalizable data is written in JDK 1.1 external data * format after calling this method. This version is needed to write * streams containing Externalizable data that can be read by * pre-JDK 1.1.6 JVMs. * * @see java.io.ObjectOutputStream#useProtocolVersion(int) * @since 1.2 */ public final static int PROTOCOL_VERSION_1 = 1; /** * A Stream Protocol Version. <p> * * This protocol is written by JVM 1.2. * * Externalizable data is written in block data mode and is * terminated with TC_ENDBLOCKDATA. Externalizable classdescriptor * flags has SC_BLOCK_DATA enabled. JVM 1.1.6 and greater can * read this format change. * * Enables writing a nonSerializable class descriptor into the * stream. The serialVersionUID of a nonSerializable class is * set to 0L. * * @see java.io.ObjectOutputStream#useProtocolVersion(int) * @see #SC_BLOCK_DATA * @since 1.2 */ public final static int PROTOCOL_VERSION_2 = 2; }
发表评论
-
文件通道解析二(文件锁,关闭通道)
2017-05-16 23:17 1065文件通道解析一(读写操作,通道数据传输等):http://do ... -
文件通道解析一(读写操作,通道数据传输等)
2017-05-16 10:04 1164Reference定义(PhantomRefere ... -
文件通道创建方式综述
2017-05-15 17:39 1066Reference定义(PhantomReference,Cl ... -
文件读写方式简单综述后续(文件,流构造)
2017-05-14 23:04 1480Java Socket通信实例:http://donald-d ... -
文件读写方式简单综述
2017-05-14 11:13 1135Java Socket通信实例:http://donald-d ... -
FileChanne定义
2017-05-12 23:28 936文件读写方式简单综述:http://donald-draper ... -
SeekableByteChannel接口定义
2017-05-11 08:43 1235ByteChannel,分散聚集通道接口的定义(SocketC ... -
FileChannel示例
2017-05-11 08:37 992前面我们看过socket通道,datagram通道,以管道Pi ... -
PipeImpl解析
2017-05-11 08:41 932ServerSocketChannel定义:http://do ... -
Pipe定义
2017-05-10 09:07 904Channel接口定义:http://donald-drape ... -
NIO-Pipe示例
2017-05-10 08:47 905PipeImpl解析:http://donald-draper ... -
DatagramChannelImpl 解析四(地址绑定,关闭通道等)
2017-05-10 08:27 776DatagramChannelImpl 解析一(初始化):ht ... -
DatagramChannelImpl 解析三(多播)
2017-05-10 08:20 1893DatagramChannelImpl 解析一(初始化):ht ... -
NIO-UDP实例
2017-05-09 12:32 1585DatagramChannelImpl 解析一(初始化):ht ... -
DatagramChannelImpl 解析二(报文发送与接收)
2017-05-09 09:03 1405DatagramChannelImpl 解析一(初始化):ht ... -
DatagramChannelImpl 解析一(初始化)
2017-05-08 21:52 1407Channel接口定义:http://donald-drape ... -
MembershipKeyImpl 简介
2017-05-08 09:11 923MembershipKey定义:http://donald-d ... -
DatagramChannel定义
2017-05-07 23:13 1228Channel接口定义:http://donald-drape ... -
MulticastChanne接口定义
2017-05-07 13:45 1136NetworkChannel接口定义:ht ... -
MembershipKey定义
2017-05-06 16:20 916package java.nio.channels; i ...
相关推荐
### Java序列化与反序列化详解 #### 一、Java序列化概述 Java序列化(Serialization)是一项重要的功能,它可以将对象的状态转化为一系列字节,从而实现对象的持久化存储或在网络上传输。序列化机制使得Java对象...
### Java序列化(Serializable)的作用与反序列化详解 #### 一、序列化是什么? 序列化是指将程序中的对象转换为字节流的过程,从而方便存储或传输这些对象。通常,序列化用于将对象的状态(即其实例变量的值,而非...
### Java序列化与反序列化的深入解析 #### 序列化的功能与意义 序列化是Java编程语言中的一项核心功能,其主要目的是将对象的状态转换为可以存储或传输的格式,便于持久化保存或网络传输。序列化并不涉及对象的...
### Java序列化原理与算法详解 #### 序言 在现代软件开发中,尤其是在网络通信和数据持久化领域,对象的序列化与反序列化扮演着至关重要的角色。Java作为一种广泛应用的编程语言,提供了强大的内置支持来实现序列化...
### Java中的序列化与反序列化详解 #### 一、概念理解 在Java中,序列化(Serialization)指的是将对象的状态转化为字节流的过程,这一过程通常用于存储对象或者在网络中传输对象。相反地,反序列化...
### Java序列化(Serializable)与反序列化详解 #### 序列化概念与应用场景 序列化是指将程序中的对象转换为一系列字节序列的过程,主要用于保存对象的状态以便将来使用或者在网络之间传输对象。Java提供了内置的...
### Java中的序列号和反序列化详解 #### 一、序列化与反序列化概述 在Java编程语言中,序列化(Serialization)是指将对象的状态转换成一系列的字节流,以便于存储或者在网络中传输的过程。而反序列化...
Java 序列化详解及简单实现实例 Java 序列化是将对象状态转换为可保持或传输的格式的过程。在 Java 中,序列化是通过实现 Serializable 接口或 Externalizable 接口来实现的。序列化的主要目的是使自定义对象持久化...
### Java对象序列化详解 #### 一、Java对象序列化概念 Java对象序列化是指将一个Java对象的状态信息转换成可以存储或传输的形式的过程。在这个过程中,对象的信息被编码成一系列字节,以便可以在文件系统中保存...
#### 一、Java序列化的概念与作用 **Java序列化**是一种将对象的状态(即其成员变量)转换为可以存储或传输的形式的过程。序列化的主要用途包括: 1. **持久化**:将对象的状态保存到磁盘上,以便将来恢复该对象的...
5. **序列化与反序列化的关系** - 序列化和反序列化后,对象的关系是深复制,而不是浅复制。反序列化生成的对象与原始对象在内存中的地址不同,但内容相同,包括对象内的引用。 6. **示例代码** ```java public ...
### Oracle WebLogic Server 反序列化补丁安装步骤详解 #### 一、概述 Oracle WebLogic Server 是一款广泛使用的中间件应用服务器,它为开发、部署和管理企业级应用程序提供了全面的支持。然而,由于反序列化漏洞的...
《Kryo 4.0.0 序列化与反序列化详解》 在软件开发中,数据序列化和反序列化是常见的操作,它能够将对象的状态转换为可存储或传输的形式,以便后续恢复。Kryo是一款高效的序列化库,尤其在Java和Scala等语言中广泛...
《GenerateSerialVersionUID:Java序列化ID自动生成工具详解》 在Java编程中,序列化是一个重要的概念,它允许对象的状态被保存以便后续恢复。而`Serializable`接口是Java实现序列化的主要方式,其中`...
4. **数据序列化与反序列化**:在TCP通信中,需要将对象转换为字节流在网络中传输,到达目的地后再还原为原来的对象,这就涉及到Java的序列化和反序列化。`java.io.ObjectOutputStream`和`java.io.ObjectInputStream...
Java的输入/输出系统是14_Java IO.doc的主题,它涵盖了文件操作、字节流、字符流、缓冲流、对象序列化以及NIO(New I/O)等内容,使得数据的读写变得简单易行。 11. **网络编程** Java的网络编程允许开发跨平台的...
`serialver`命令用于生成或验证类的`serialVersionUID`,这是Java序列化机制中的一个重要概念,用于确保序列化的兼容性。 **语法**: ``` serialver[命令选项] ``` **功能说明**: `serialver`通过分析类的结构...
3. 数据序列化与反序列化:为了在网络上传输消息,数据需要被序列化为字节流。Java的Serializable接口和ObjectOutputStream/ObjectInputStream类用于实现这一功能,确保对象能够在网络间安全传输。 二、聊天系统...
序列化是Java内置的持久化机制,允许将实现了`Serializable`接口的类对象转化为二进制字节流,保存到磁盘并能恢复。对于简单的应用,序列化可以满足Java对象的持久化需求。例如,以下`Person`类展示了如何实现序列化...