目次 | 前の項目 | 次の項目 | Java オブジェクト直列化仕様 |
クラスObjectInputStream
は、オブジェクトの直列化復元を実装するためのものです。このクラスは、すでに直列化復元されたオブジェクトセットなどのストリームの状態を管理します。このクラスのメソッドを使えば、ObjectOutputStream
によって書き込まれたストリームから、プリミティブ型やオブジェクトを読み込むことができます。このクラスは、それが参照するオブジェクトをストリームから復元します。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 Object readUnshared() 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
メソッドによって書き込まれたヘッダとバージョンを検査します。セキュリティマネージャがインストールされている場合、このコンストラクタは、readFields
メソッドまたはreadUnshared
メソッド、あるいはその両方をオーバーライドするサブクラスのコンストラクタによって直接または間接的に呼び出されたときに、"enableSubclassImplementation"
SerializablePermission
のチェックを行います。
注 -ObjectInputStream
コンストラクタは、直列化ストリームヘッダの読み込みが完了するまでブロックされます。コードがObjectInputStream
の構築を待機しているときに、直列化ストリームに対して対応するObjectOutputStream
が作成されていない場合は、デッドロックが発生します。ObjectInputStream
コンストラクタは、ヘッダがそのストリームに書き込まれるまでブロックされ、ヘッダはObjectOutputStream
コンストラクタが実行されるまでストリームに書き込まれないためです。この問題は、ObjectInputStream
が構築される前に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 がスローされます。このとき、停止を引き起こした例外が引数として指定されます。ストリームコンテキストは前に述べたようにリセットされます。
ストリームから非共有オブジェクトを読み込むには、
readUnshared
メソッドを使用します。このメソッドは、後続のreadObject
およびreadUnshared
の呼び出しが、元のreadUnshared
の呼び出しによって返された直列化復元インスタンスへの追加参照を返すことができない点を除いては、readObject
と同じです。具体的には、次のようになります。
readUnshared
を介してオブジェクトの直列化復元を行うと、返されたオブジェクトに関連付けられたストリームハンドルが無効になります。このこと自体は、readUnshared
によって返された参照が一意であることを常に保証するものではありません。直列化復元されたオブジェクトは、readResolve
メソッドを定義して、ほかの組織が見ることができるオブジェクトを返すことがあります。また、readUnshared
が、ストリーム内のほかの場所や外部機関から取得可能なClass
オブジェクトを返すこともあります。ただし、オブジェクトがjava.lang.Class
のインスタンスではなく、readResolve
メソッドを定義しない場合は、readUnshared
を使うことで、返されたオブジェクト参照が一意であること、および基になるデータストリームが処理済みであっても、それを作成したObjectInputStream
から再度取得されないことが保証されます。この保証は、readUnshared
によって返される基本レベルのオブジェクトだけに適用され、返されたオブジェクトのグラフ内で一時的に参照されるサブオブジェクトには一切適用されません。ストリームからフィールドおよびオブジェクトを読み込むには、
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
のサブクラスによって非標準形式で記述されたクラス記述子が読み込むためのこのメソッドは、ObjectInputStream
のサブクラスによってオーバーライドされます。デフォルトでは、このメソッドは、「6.4 ストリーム形式の文法」で説明している形式に従ってクラス記述子を読み込みます。
resolveClass
メソッドは、直列化復元されている間と、そのクラス記述子が読み込まれたあとで呼び出されます。サブクラスは、このメソッドを拡張して、ObjectOutputStream
の対応するサブクラスによって書き込まれたクラスの他の情報を読むことができます。このメソッドは、与えられた名前とserialVersionUID
を持つクラスを見つけ、返さなければなりません。デフォルトの実装では、このクラスは、クラスローダを持つreadObject
のもっとも近い呼び出し側のクラスローダを呼び出すことによって、見つけることができます。このクラスが見つからないと、ClassNotFoundException
がスローされます。JDKTM 1.1.6 より前のバージョンでは、resolveClass
メソッドは、ストリーム内のクラス名と同じ、完全指定されたクラス名を返す必要がありました。JDK 1.1.6 以降のバージョンでは、リリースごとにパッケージの名前を変更できるようにするために、resolveClass
メソッドは、同じ基底クラス名および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
に private なデータを割り当てず、ファイナルのreadObject
メソッドはreadObjectOverride
メソッドを呼び出してから復帰することを示すフラグを設定します。ほかのすべてのObjectInputStream
メソッドは、ファイナルではないので、サブクラスによって直接オーバーライドされます。