クラスオブジェクトは次のオブジェクトによって表されます。
配列は次の要素によって表されます。
writeObject/readObject メソッドがあれば、writeObject メソッドによって書き込まれた、プリミティブ型の任意指定のオブジェクトおよび/またはブロックデータレコードと、それに続いて endBlockData がある場合がある。
writeObject メソッドの中でストリームに書き込まれたのか、writeObject メソッドの外から直接ストリームに書き込まれたのかには関係ありません。このデータは、対応する readObject メソッドによって読み込むか、ストリームから直接読み込むことができます。writeObject によって書き込まれたオブジェクトは、前に書き込まれたブロックデータレコードがあればそれを停止し、正規オブジェクト、null、またはバック参照のうち適切なものとして書き込まれます。ブロックデータレコードでは、エラー回復によって任意指定データを破棄することができます。クラスの中から呼び出された場合には、ストリームはデータやオブジェクトを endBlockData まで破棄することができます。
下のテーブルはこの文法を示したものです。非終端記号はイタリックで、終端記号は固定幅のフォントで示します。非終端の定義には、その後に ":"が続きます。定義には 1 つまたは複数の代替定義が続き、それぞれが別の行に示されます。下のテーブルはその表記法を示しています。
| 表記法 | 意味 |
|---|---|
| (datatype) | このトークンには、バイトなどのデータ型が指定されます。 |
| token[n] | このトークンの事前に定義されたオカレンス数。これは配列です。 |
| x0001 | 16 進数で表したリテラル値。16 進数の桁数がその値のサイズを表します。 |
| <xxx> | ストリームから読み込まれた値であり、配列の長さを示すために使用されます。 |
stream: magic version contents
contents: content contents content
content: object blockdata
object: newObject newClass newArray newString newClassDesc prevObject nullReference exception TC_RESET
newClass: TC_CLASS classDesc newHandle
classDesc: newClassDesc nullReference (ClassDesc)prevObject // オブジェクトの型は 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
objectDesc: obj_typecode fieldName className
fieldName: (utf)
className: (String)object // フィールドの型を含む文字列
classAnnotation: endBlockData contents endBlockData // 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[] // 各クラスのデータ
classdata: nowrclass // SC_WRRD_METHOD & !classDescFlags wrclass objectAnnotation // SC_WRRD_METHOD & classDescFlags
nowrclass: values // クラス記述子の順序になったフィールド
wrclass: nowrclass
objectAnnotation: endBlockData contents endBlockData // 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 reset (Throwable)object reset
resetContext: TC_RESET
magic: STREAM_MAGIC
version : STREAM_VERSION
values: // サイズと型は現行オブジェクトに対し // classDescによって記述される。
newHandle: // 順序にある次の番号が直列化または直列化復元 // されているオブジェクトに割り当てられる。
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_WRITE_METHOD = 0x01; final static byte SC_SERIALIZABLE = 0x02; final static byte SC_EXTERNALIZABLE = 0x04;
ストリームを書き込んだクラスが java.io.Serializable を拡張したが、java.io.Externalizable は拡張しなかった場合は、フラグ SC_SERIALIZABLE がオンに設定されます。そのストリームを読み込むクラスもまた Serializable を拡張しなければなりません。デフォルトの直列化メカニズムが使用されます。
ストリームを書き込んだクラスが java.io.Externalizable を拡張した場合は、フラグ SC_EXTERNALIZABLE がオンに設定されます。そのデータを読み込むクラスもまた、 Externalizable を拡張しなければなりません。このデータはその writeExternal と readExternal メソッドを使って読み込まれます。
class List implements java.io.Serializable {
int value;
List next;
public static void main(String[] args) {
try {
List list1 = new List();
List list2 = new List();
list1.value = 17;
list1.next = list2;
list2.value = 19;
list2.next = null;
ByteArrayOutputStream o = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(o);
out.writeObject(list1);
out.writeObject(list2);
out.flush();
...
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
00: ac ed 00 05 73 72 00 04 4c 69 73 74 69 c8 8a 15 >....sr..Listi...<
10: 40 16 ae 68 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.~..<