目次 | 前の項目 | 次の項目 | Java オブジェクト直列化仕様 |
クラスObjectInputStream
は、オブジェクトの直列化復元を実装するためのものです。このクラスは、すでに直列化復元されたオブ ジェクトセットなどのストリームの状態を管理します。このクラスのメソッドを使えば、ObjectOu tputStream
によって書き込まれたストリームから、プリミティブ型やオブジェクトを読み込むことができます。この クラスは、それが参照するオブジェクトをストリームから復元します。package java.io; public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants { public ObjectInputStream(InputStream in) throws StreamCorruptedException, IOException;public final Object readObject() throws OptionalDataException, ClassNotFoundException, IOException; public void defaultReadObject() throws IOException, ClassNotFoundException, NotActiveException; public GetField readFields() throws IOException; public synchronized void registerValidation( ObjectInputValidation obj, int prio) throws NotActiveException, InvalidObjectException; protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException; protected Class resolveClass(ObjectStreamClass v) throws IOException, ClassNotFoundException; protected Object resolveObject(Object obj) throws IOException; protected boolean enableResolveObject(boolean enable) throws SecurityException; protected void readStreamHeader() throws IOException, StreamCorruptedException; public int read() throws IOException; public int read(byte[] data, int offset, int length) throws IOException public int available() throws IOException; public void close() throws IOException; public boolean readBoolean() throws IOException; public byte readByte() throws IOException; public int readUnsignedByte() throws IOException; public short readShort() throws IOException; public int readUnsignedShort() throws IOException; public char readChar() throws IOException; public int readInt() throws IOException; public long readLong() throws IOException; public float readFloat() throws IOException; public double readDouble() throws IOException; public void readFully(byte[] data) throws IOException; public void readFully(byte[] data, int offset, int size) throws IOException; public int skipBytes(int len) throws IOException; public String readLine() throws IOException; public String readUTF() throws IOException; // Class to provide access to serializable fields. static abstract public class GetField { public ObjectStreamClass getObjectStreamClass(); public boolean defaulted(String name) throws IOException, IllegalArgumentException; public char get(String name, char default) throws IOException, IllegalArgumentException; public boolean get(String name, boolean default) throws IOException, IllegalArgumentException; public byte get(String name, byte default) throws IOException, IllegalArgumentException; public short get(String name, short default) throws IOException, IllegalArgumentException; public int get(String name, int default) throws IOException, IllegalArgumentException; public long get(String name, long default) throws IOException, IllegalArgumentException; public float get(String name, float default) throws IOException, IllegalArgumentException; public double get(String name, double default) throws IOException, IllegalArgumentException; public Object get(String name, Object default) throws IOException, IllegalArgumentException; } protected ObjectInputStream() throws StreamCorruptedException, IOException; protected readObjectOverride() throws OptionalDataException, ClassNotFoundException, IOException; }ObjectInputStream
コンストラクタにはInputStream
が必要です。このコンストラクタは、readStreamHeader
を呼び出して読み込み、対応するObjectOutputStream.writeStreamHeader
メソッドによって書き込まれたヘッダとバージョンを検査します。
注:ObjectInputStream
コンストラクタは、直列化ストリームヘッダの読み込みが完了するまでブロックされます。コードがObjectInputStream
の構築を待機しているときに、直列化ストリームに対して対応するObjectOutputStream
が作成されていない場合は、デッドロックが発生します。ObjectInputStream
コンストラクタは、ヘッダがそのストリームに書き込まれるまでブロックされ、ヘッダは、Object OutputStream
コンストラクタが実行されるまでストリームに書き込まれないためです。この問題は、ObjectInpu tStream
が構築される前にObjectOutputStream
を作成するか、ObjectInputStream
の構築の完了およびObjectOutputStream
の作成の間のタイミング依存関係を解除すると解決できます。
ストリームからオブジェクトを直列化復元するには、readObject
メソッドを使用します。このメソッドは、このストリームを読んで、オブジェクトを再構築します。
ObjectInputStream
サブクラスが実装をオーバーライドしている場合は、readObjectOverride
メソッドを呼び出し、戻します。実装し直す方法については、この節の最後で説明します。
Class
であれば、その
ObjectStreamClass
記述子を読み、それとそのハンドルを、認識されているオブジェクトセットに追加し、対応する
Class
オブジェクトを返します。
ObjectStreamClass
であれば、その名前と serialVersionUID
とフィールドを読み、そのオブジェクトとそのハンドルを、認識されているオブジェクトセットに追加し
ます。このストリームに対し resolveClass
メソッドを呼び出して、この記述子のローカルクラスを入手します。そのクラスが見つからないときは例
外をスローします。ObjectStreamClass
オブジェクトを返します。
ObjectStreamClass
と配列の長さを読みます。その配列を割り当て、そのオブジェクトとそのハンドルを、認識されているオ
ブジェクトセットに追加します。型に適したメソッドを使って各要素を読み込み、配列に割り当てて、手
順 11 に進みます。
ObjectStreamClass
がストリームから読み込まれます。その
ObjectStreamClass
のローカルクラスが取り出されます。このクラスは、直列化可能か外部化可能でなければなりません。
readObject
メソッドか、これらが定義されていなければ、defaultReadObject
メソッドが呼び出されて、各クラスのフィールドが復元されます。直列化復元時には、直列化可能クラス
に対して、フィールドの初期化子およびコンストラクタは実行されません。通常、このストリームを書き
込んだクラスのバージョンは、このストリームを読み込むクラスと同じです。この場合、ストリームのオ
ブジェクトのすべてのスーパータイプは、現在ロードされているクラスのスーパータイプと一致します。
このストリームを書き込んだクラスのバージョンのスーパータイプが、ロードされているクラスのスーパ
ータイプと異なる場合は、ObjectInputStream
で異なるクラスの状態を復元したり、初期化したりする際、いっそうの注意が必要です。この場合には、
すべてのクラスを調べて、ストリームにあるデータと、復元するオブジェクトのクラスとを比較する必要
があります。ストリームにはあるがオブジェクトにはないクラスのデータは破棄されます。オブジェクト
にはあるがストリームにはないクラスの場合には、そのクラスのフィールドが、デフォルトの直列化によ
ってデフォルト値に設定されます。
readExternal
メソッドが呼び出され、そのオブジェクトの内容が復元されます。
ObjectInputStream
のサブクラスによって、置換を処理します。
置換が行われた場合、認識されているオブジェクトのテーブルが更新されるので、置換オブジェクトがハ ンドルに関連付けられます。そのあと、置換オブジェクトがreadObject
から返されます。プリミティブ型を読むためのすべてのメソッドは、ストリームのブロックデータレコードからバイトだけ を使用します。ストリームの次のアイテムがオブジェクトのときにプリミティブデータの読み込みが行わ れると、読み込みメソッドは -1 か EOFException のうちで適切な方を返します。プリミティブ型の値は、
DataInputStream
によってブロックデータレコードから読み込まれます。スローされた例外は、そのトラバースの間に起きたエラーか、基本のストリームで起きた例外を反映した ものです。例外がスローされた場合、基本のストリームは不明で使用不能な状態のままです。
ストリームでリセットトークンが起こると、ストリームのすべての状態は破棄されます。認識されている オブジェクトセットはクリアされます。
ストリームで例外トークンが起こると、その例外が読み込まれ、新しい WriteAbortedException がスローされます。このとき、停止を引き起こした例外が引数として指定されます。ストリームコンテキ ストは前に述べたようにリセットされます。
ストリームからフィールドおよびオブジェクトを読み込むには、
defaultReadObject
メソッドを使用します。このメソッドは、ストリームのクラス記述子を使って、名前と型による標準の順 序でストリームからそれらのフィールドを読み込みます。それらの値は、名前によって現行クラスの対応 するフィールドに代入されます。バージョン管理機構の詳細については、「5.5 互換性のある JavaTM の型展開」を参照してください。ストリーム内にないオブジェクトのフィールドは、そのデフォルト 値に設定されます。ストリームにあるがオブジェクトにない値は、破棄されます。このような状態は主に 、前のバージョンにはなかったフィールドを、クラスのあとのバージョンに追加で書き込んだ場合に起こ ります。このメソッドは、クラスのフィールドを復元している間にreadObject
メソッドからのみ呼び出すことができます。それ以外のときに呼び出すと、NotActiveException がスローされます。
readFields
メソッドは、ストリームから直列化可能フィールドの値を読み取り、GetField
クラスを使ってその値を使用できるようにします。readFields
メソッドは、直列化可能クラスのreadObject
メソッド内からしか呼び出すことができません。また、このメソッドは、1 回しか呼び出すことができず、defaultReadObject
がすでに呼び出されている場合は呼び出せません。GetFields
オブジェクトは、現在のオブジェクトであるObjectStreamClass
を使ってこのクラス用に取得できるフィールドを確認します。readFields
によって返されるGetFields
オブジェクトは、そのクラスのreadObject
メソッドへの呼び出しの間だけ有効です。フィールドは、任意の順序で取得できます。追加データの読み 込みは、readFields
が呼び出されたあとに、ストリームから直接読み込む場合だけ可能です。メソッドとオブジェクトが復元されれば、
registerValidation
メソッドを呼び出して、コールバックを要求することができます。ただし、コールバックオブジェクトがreadObject
の元の呼び出し側に返される前に呼び出さなければなりません。有効化コールバックの順序は、優先順次 で制御することができます。高い値のコールバックは、低い値のものより前に呼び出されます。有効にさ れるオブジェクトは、ObjectInputValidation
インタフェースをサポートし、validateObject
メソッドを実装していなければなりません。有効化を登録するのは、クラスのreadObject
メソッドを呼び出す間でなければなりません。そうでないと、NotActiveException がスローされます。registerValidation
に指定されたコールバックオブジェクトが null の場合、InvalidObjectException がスローされます。JavaTM SDK, Standard Edition, v1.3 から、すべての
ObjectStreamClass
オブジェクトを読み込むときにreadClassDescriptor
メソッドが使用されています。 直列化ストリーム内でObjectInputStream
の次の項目がクラス記述子の場合は、readClassDescriptor
が呼び出されます。writeClassDescriptor
メソッドをオーバーライドしたObjectOutputStream
のサブクラスによって非標準形式で記述されたクラス記述子が読み込むためのこのメソッドは、Ob jectInputStream
のサブクラスによってオーバーライドされます。デフォルトでは、このメソッドは、「6.4 ストリーム形式の文法」で説明している形式に従ってクラス記述子を読み込みます。
resolveClass
メソッドは、クラスが直列化復元されている間と、そのクラス記述子が読み込まれたあとで呼び出されま す。サブクラスは、このメソッドを拡張して、ObjectOutputStream
の対応するサブクラスによって書き込まれたクラスの他の情報を読むことができます。このメソッドは、 与えられた名前とserialVersionUID
を持つクラスを見つけ、返さなければなりません。デフォルトの実装では、このクラスは、クラスローダ を持つreadObject
のもっとも近い呼び出し側のクラスローダを呼び出すことによって、見つけることができます。このクラ スが見つからないと、ClassNotFoundException
が通常スローされます。JDKTM 1.1.6 より前のバージョンでは、resolveClass
メソッドは、ストリーム内のクラス名と同じ、完全修飾クラス名を返す必要がありました。JDKTM 1.1.6 以降のバージョンでは、どのリリースでもパッケージの名前を変更できるようにするために、reso lveClass
メソッドが返すのは、同じ基底クラス名とSerialVersionUID
を持つクラスだけになりました。
resolveObject
メソッドは、信頼できるサブクラスが、直列化復元の際に、あるオブジェクトをにモニター、あるいは他 のオブジェクトに代用するときに使用します。解釈処理する最初のオブジェクトに対してreadObject
を呼び出す前に、enableResolveObject
を呼び出して、オブジェクトの解析処理を明示的に使用可能にしなければなりません。オブジェクトの解 析処理を使用可能にすると、それぞれの直列化可能オブジェクトがreadObject
から最初に返される直前に、resolveObject
は一度だけ呼び出されます。resolveObject
メソッドは、特別に処理されるクラスであるClass
、ObjectStreamClass
、String
、および配列の、オブジ ェクトに対しては呼び出されません。サブクラスのresolveObject
の実装では、オリジナルの代わりに代入されたり返されたりする置換オブジェクトが、返される場合があ ります。返されるオブジェクトは、一貫性があり、元のオブジェクトの参照に必ず代入できる型のもので なければなりません。 そうでないと、ClassCastException が返されます。すべての代入では型の検査が行われます。ストリームにおける元のオブジェクトへのすべ ての参照は、置換オブジェクトへの参照によって置き換えられます。
enableResolveObject
メソッドは、ObjectOutputStream
の信頼できるサブクラスが、直列化復元の際に、あるオブジェクトをモニター、あるいは、他のオブジェ クトに代用するときに使用します。オブジェクトの置換は、enableResolveObject
が true 値で呼び出されるまでは、オフになっています。また、使用可能にしたあとで、false に設定して、使用不可にされる場合があります。前の設定が返されます。enableResolveObject メソッドは、直列化の際にストリームが置換を要求する権限があるかどうかを検査します。オブジェクト の private 状態が意図せずに変更されることのないように、信頼できるストリームだけしか
resolveObject
を使用することはできません。信頼できるクラスとは、クラスローダが null に等しいか、置換を有効にすることを許可するセキュリティ保護ドメインに属するクラスのことです。
ObjectInputStream
のサブクラスがシステムドメインの一部でないとみなされる場合は、enableResolveObject
の呼び出し許可をObjectInputStream
のサブクラスに与える行を、セキュリティポリシーファイルに追加する必要があります。追加するSerializablePermission
は、"enableSubstitution"
です。ObjectStreamClass
のサブクラスの保護ドメインに、enableResolveObject
の呼び出しによる"enableSubstitution"
の権限がない場合は、AccessControlException がスローされます。セキュリティモデルの詳細は、JavaTM セキュリティアーキテクチャ (JDKTM 1.2) のドキュメントを参照してください。
readStreamHeader
メソッドは、ストリームのマジック番号とバージョンを読み込み、検査します。それらが一致しないと、 StreamCorruptedMismatch がスローされます。直列化復元の実装をオーバーライドするには、
ObjectInputStream
のサブクラスは、保護された引数なしのObjectInputStream
コンストラクタを呼び出す必要があります。SerializablePermission "enableSubclassImplementation"
の引数なしのコンストラクタ内にはセキュリティチェックがあり、信頼できるクラスだけにデフォルトの 実装のオーバーライドを許可することを保証します。このコンストラクタは、ObjectInputStream< /code> に private なデータを割り当てず、ファイナルの
readObject
メソッドはreadObjectOverride
メソッドを呼び出してから復帰することを示すフラグを設定します。ほかのすべてのObjectInputStream
メソッドは、ファイナルではないので、サブクラスによって直接オーバーライドされます。