| 目次 | 前の項目 | 次の項目 | 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メソッドは、ファイナルではないので、サブクラスによって直接オーバーライドされます。