A class object is represented by:
Arrays are represented by
writeObject
/readObject
methods there may be optional objects and/or block-data records of primitive types written by the writeObject
method followed by an endBlockData code.
writeObject
method or written directly to the stream from outside a writeObject
method. This data may only be read by the corresponding readObject
methods or directly from the stream. Objects written by writeObject
terminate any previous block-data record and are written as regular objects, or null or back references as appropriate. The block-data records allow error recovery to discard any optional data. When called from within a class, the stream can discard any data or objects until the endBlockData.
The table below contains the grammar. Non-terminal symbols are show in italics, Terminal symbols in a fixed width font. Definitions of non-terminals are followed by a ":". The definition is followed by one or more alternatives each on a separate line. The notation in the table is as follows:
(datatype
) This token has the data type specified, e.g. (byte).
stream: magic version contents
contents: content contents content
content: object blockdata
object: newObject newClass newArray newString newClassDesc prevObject nullReference exception
newClass: TC_CLASS classDesc newHandle
classDesc: newClassDesc nullReference (ClassDesc)prevObject // an object required to be of type ClassDesc
superClassDesc: classDesc
newClassDesc: TC_CLASSDESC className serialVersionUID newHandle classDescInfo
classDescInfo: classDescFlags fields classAnnotation superClassDesc
className: (utf)
serialVersionUID: (long)
classDescFlags: (byte)
fields: (short)<count> fieldDesc[count]
fieldDesc: primitiveDesc objectDesc
primitiveDesc: prim_typecode fieldName modifiers
objectDesc: obj_typecode fieldName modifiers className
fieldName: (utf)
modifiers: (short)
className: (String)object // String containing the field's type
classAnnotation: endBlockData contents endBlockData // contents written by annotateClass
prim_typecode: `B' // byte `C' // char `D' // double `F' // float `I' // integer `J' // long `S' // short `Z' // boolean
obj_typecode: `[` // array `L' // object
newArray: TC_ARRAY classDesc newHandle (int)<size> values[size]
newObject: TC_OBJECT classDesc newHandle classdata[] // data for each class
classdata: nowrclass // SC_WRRD_METHOD & !classDescFlags wrclass objectAnnotation // SC_WRRD_METHOD & classDescFlags
nowrclass: values // fields in order of class descriptor
wrclass: nowrclass
objectAnnotation: endBlockData contents endBlockData // contents written by writeObject
blockdata: TC_BLOCKDATA (byte)<size> (byte)[size]
blockdatalong: TC_BLOCKDATALONG (int)<size> (byte)[size]
endBlockData : TC_ENDBLOCKDATA
newString: TC_STRING newHandle (utf)
prevObject : TC_REFERENCE (int)handle
nullReference : TC_NULL
exception: TC_EXCEPTION (Throwable)object // A java.lang.Throwable object
resetContext: TC_RESET
magic: STREAM_MAGIC
version : STREAM_VERSION
values: // The size and types are described by the // classDesc for the current object
newHandle: // The next number in sequence is assigned // to the object being serialized or deserialized
final static short STREAM_MAGIC = (short)0xaced; final static short STREAM_VERSION = 5; final static byte TC_NULL = (byte)0x70; final static byte TC_REFERENCE = (byte)0x71; final static byte TC_CLASSDESC = (byte)0x72; final static byte TC_OBJECT = (byte)0x73; final static byte TC_STRING = (byte)0x74; final static byte TC_ARRAY = (byte)0x75; final static byte TC_CLASS = (byte)0x76; final static byte TC_BLOCKDATA = (byte)0x77; final static byte TC_ENDBLOCKDATA = (byte)0x78; final static byte TC_RESET = (byte)0x79; final static byte TC_BLOCKDATALONG = (byte)0x7A; final static byte TC_EXCEPTION = (byte)0x7B; final static byte SC_WRRD_METHODS = 0x01; final static byte SC_SERIALIZABLE = 0x02; final static byte SC_EXTERNALIZABLE = 0x04;
class List { int value; List next; public static void main(String[] args) { list list1 = new list(); list list2 = new list(); list1.value = 17; list1.next = list2; list2.value = 19; list2.next = null; ObjectOutputStream out = ...; out.writeObject(list1); out.writeObject(list2); }
00: ac ed 00 05 73 72 00 04 4c 69 73 74 2f 0b 17 f6 >....sr..List/...<
10: 5a 0f bc a7 02 00 02 49 00 05 76 61 6c 75 65 4c >Z......I..valueL<
20: 00 04 6e 65 78 74 74 00 06 4c 4c 69 73 74 3b 78 >..nextt..LList;x<
30: 70 00 00 00 11 73 71 00 7e 00 00 00 00 00 13 70 >p....sq.~......p<
40: 71 00 7e 00 03 >q.~..<