モジュール java.base
パッケージ java.io

クラスObjectInputStream

java.lang.Object
java.io.InputStream
java.io.ObjectInputStream
すべての実装されたインタフェース:
Closeable, DataInput, ObjectInput, ObjectStreamConstants, AutoCloseable

public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants
事前にObjectOutputStreamを使って作成されたプリミティブ・データとプリミティブ・オブジェクトを直列化復元します。

警告: 信頼できないデータの直列化復元は、本質的に危険であり、回避する必要があります。 「Java SEに対するセキュア・コーディングのガイドライン」の"直列化および直列化復元"セクションに従って、信頼できないデータを慎重に検証する必要があります。 「直列化フィルタリング」では、シリアル・フィルタの使いやすさに関するベスト・プラクティスについて説明します。

直列化復元攻撃を無効にするキーは、任意のクラスのインスタンスが直列化復元されないようにし、そのメソッドの直接または間接的な実行を防ぐことです。 ObjectInputFilterはフィルタの使用方法を示し、ObjectInputFilter.Configはフィルタおよびフィルタ・ファクトリの構成方法を示します。 各ストリームには、直列化復元中にクラスおよびリソース制限をチェックするオプションの直列化復元フィルタがあります。 JVM全体のフィルタ・ファクトリにより、ObjectInputStreamごとにフィルタを設定でき、ストリームから読み取られるすべてのオブジェクトをチェックできます。 「ObjectInputStreamコンストラクタ」は、setObjectInputFilter(java.io.ObjectInputFilter)によって更新または置換される初期フィルタを選択するために、フィルタ・ファクトリを起動します。

ObjectInputStreamにフィルタがある場合、ObjectInputFilterでは、クラス、配列の長さ、ストリーム内の参照数、深さおよび入力ストリームから消費されたバイト数が許可され、そうでない場合には、直列化復元を終了できます。

ObjectOutputStreamとObjectInputStreamは、FileOutputStreamまたはFileInputStreamとともに使えば、アプリケーションに、オブジェクトのグラフのための持続的なストレージを提供することができます。 ObjectInputStreamは、事前に直列化されたオブジェクトを元に戻すために使います。 ほかの使用方法としては、ソケット・ストリームの使用による、ホスト間でのオブジェクトの受け渡しや、リモート通信システムでの属性やパラメータの整列や整列解除があります。

ObjectInputStreamは、ストリームから作成されたオブジェクト・グラフでのすべての型のオブジェクトが、Java Virtual Machineに存在するクラスに確実にマッチするようにします。 クラスは、標準のメカニズムを使って必要に応じてロードされます。

ストリームから読み込むことができるのは、java.io.Serializableインタフェースかjava.io.Externalizableインタフェースをサポートするオブジェクトだけです。

オブジェクトをストリームから読み込むにはreadObjectメソッドを使います。 希望の型を取得するには、Javaの安全なキャストを使う必要があります。 Javaでは、文字列と配列はオブジェクトで、直列化の間はオブジェクトとして扱われます。 それらを読み込む際には、希望の型にキャストされている必要があります。

プリミティブ・データ型をストリームから読み込むには、DataInputの適切なメソッドを使います。

オブジェクトのデフォルトの直列化復元メカニズムは、各フィールドの内容を、書き込まれたときの状態に戻します。 transientまたはstaticと宣言されたフィールドは、直列化復元処理では無視されます。 ほかのオブジェクトを参照すると、それらのオブジェクトは、必要に応じてストリームから読み込まれます。 オブジェクトのグラフは、参照共有メカニズムを使って正しく復元されます。 直列化復元が行われるときには、常に新しいオブジェクトが割り当てられ、それによって既存のオブジェクトへの上書きが防止されます。

オブジェクトの読込みは、新しいオブジェクトのコンストラクタの実行に似ています。 メモリーがオブジェクトに割り当てられ、ゼロ(NULL)に初期化されます。 直列化可能でないクラスに対して、引数なしのコンストラクタが呼び出されたあと、直列化可能クラスのフィールドが、java.lang.Objectにもっとも近いクラスから始まって、もっともオブジェクトに固有のクラスで終わるストリームから復元されます。

たとえば、ObjectOutputStreamの例で記述されたストリームから読み取る場合:

    try (FileInputStream fis = new FileInputStream("t.tmp");
         ObjectInputStream ois = new ObjectInputStream(fis)) {
        String label = (String) ois.readObject();
        LocalDateTime dateTime = (LocalDateTime) ois.readObject();
        // Use label and dateTime
    } catch (Exception ex) {
        // handle exception
    }

クラスは、インタフェースjava.io.Serializableまたはjava.io.Externalizableを実装することによって、クラスがどのように直列化されるかを制御します。

Serializableインタフェースを実装することによって、オブジェクトの直列化が、オブジェクトの状態全体の保存と復元を行うことが可能になり、またクラスが、ストリームの書込み時とストリームの読込み時の間に展開することが可能になります。 オブジェクトの直列化は、オブジェクト間の参照を自動的にトラバースし、オブジェクト・グラフの全体を保存および復元します。

直列化および直列化復元プロセス中に特別な処理を必要とする直列化可能なクラスは、次のシグネチャを持つメソッドを実装する必要があります:

    private void writeObject(java.io.ObjectOutputStream stream)
        throws IOException;
    private void readObject(java.io.ObjectInputStream stream)
        throws IOException, ClassNotFoundException;
    private void readObjectNoData()
        throws ObjectStreamException;

メソッド名、修飾子、戻り型、およびパラメータの数とタイプは、直列化または直列化復元で使用されるメソッドと完全に一致する必要があります。 これらのシグネチャと一致するチェック済例外をスローするためにのみ、メソッドを宣言する必要があります。

readObjectメソッドは、対応するwriteObjectメソッドによってストリームに書き込まれたデータを使用する特定のクラスについて、オブジェクトの状態を読み込みおよび復元する責任を持ちます。 このメソッドは、そのスーパー・クラスやサブクラスに属する状態に関与する必要はありません。 状態を復元するには、個々のフィールドについてObjectInputStreamからデータを読み込み、オブジェクトの適切なフィールドへの割り当てを行います。 プリミティブ・データ型の読込みは、DataInputによってサポートされます。

オブジェクト・データを読み込もうとするときに、その位置が対応するwriteObjectメソッドによって書き込まれたカスタム・データの境界を超えている場合は、eofフィールドの値がtrueの状態でOptionalDataExceptionがスローされます。 オブジェクトを直列化して読み込もうとするときに、その位置が割当て済みデータの終わりを超えている場合は、ストリームの場合と同様に、データの終わりを示す例外が返されます。つまり、バイト単位の読込みでは、バイトが読み込まれたときに -1が返されます。プリミティブ読込みでは、EOFExceptionがスローされます。 対応するwriteObjectメソッドがない場合は、デフォルトの直列化データの終わりが割当て済みデータの終わりになります。

プリミティブ読み込みとオブジェクト読込みがreadExternalメソッドから呼び出された場合は、両方とも同じように動作します。ストリームの位置が対応するwriteExternalメソッドによって書き込まれたデータの終わりにある場合、オブジェクト読込みではeofがtrueに設定された状態でOptionalDataExceptionがスローされ、バイトの読込みでは -1を返し、プリミティブ読込みではEOFExceptionがスローされます。 ただし、古いObjectStreamConstants.PROTOCOL_VERSION_1プロトコルを使用して書き込まれたストリームでは、この動作は適用されません。writeExternalメソッドと異なり、データの終わりが書き込まれないため、データの終わりを検出できないためです。

readObjectNoDataメソッドは、あるクラスが直列化復元されるオブジェクトのスーパー・クラスとして直列化ストリームに指定されていないときに、そのクラスについてそのオブジェクトの状態を初期化します。 これは、受取り側が送り側とは異なるバージョンの直列化復元されたインスタンスのクラスを使用し、受取り側のバージョンが送り側のバージョンによって継承されないクラスを継承する場合に発生する可能性があります。 また、直列化ストリームが改変された場合にも発生することがあります。したがって、readObjectNoDataは、「悪意のある」または不正なソース・ストリームであっても、直列化復元されたオブジェクトを正しく初期化するのに役立ちます。

直列化は、java.io.Serializableインタフェースを実装しないオブジェクトのフィールドの読込みや、それらのフィールドへの値の割当ては行いません。 直列化可能でないオブジェクトのサブクラスを直列化可能にすることができます。 この場合、直列化可能でないクラスは、そのフィールドを初期化できるようにするため、引数なしのコンストラクタを持つ必要があります。 この場合、直列化可能でないクラスの状態を保存および復元するのは、サブクラスの責任になります。 そのクラスのフィールドがアクセス可能である(public、package、またはprotected)場合、あるいは状態の復元に利用できるsetメソッドやgetメソッドがある場合がしばしばあります。

オブジェクトを直列化復元する間に発生したすべての例外は、ObjectInputStreamにキャッチされ、読込み処理を異常終了させます。

Externalizableインタフェースを実装すると、オブジェクトの直列化された形式の内容および形式をオブジェクト側が完全に制御することが可能になります。 ExternalizableインタフェースのメソッドであるwriteExternalとreadExternalは、オブジェクトの状態を保存および復元するために呼び出されます。 これらのメソッドは、クラスによって実装された場合には、ObjectOutputとObjectInputのすべてのメソッドを使って、自身の状態の書き込みおよび読込みを行うことができます。 どのようなバージョンであっても処理できるようにするのは、オブジェクトの責任です。

enum定数の直列化復元は、通常の直列化可能または外部化可能オブジェクトとは異なります。 enum定数の直列化された形式を構成するのは、その名前だけです。定数のフィールド値は転送されません。 enum定数を直列化復元するには、ObjectInputStreamでストリームから定数名を読み込みます。次に、enum定数の基底型と受け取った定数名を引数としてstaticメソッドのEnum.valueOf(Class, String)を呼び出し、直列化復元された定数を取得します。 他の直列化可能または外部化可能オブジェクトと同様に、enum定数は直列化ストリームにその後出現する後方参照のターゲットとして機能できます。 enum定数を直列化復元するプロセスをカスタマイズすることはできません。enum型で定義された、クラス固有のreadObject、readObjectNoData、およびreadResolveメソッドはどれも直列化復元の間は無視されます。 同様に、serialPersistentFieldsまたはserialVersionUIDのフィールド宣言もすべて無視されます。すべてのenum型は0Lで固定されたserialVersionUIDを持ちます。

レコードの直列化は、通常の直列化可能オブジェクトまたは外部化可能オブジェクトとは異なります。 レコードの直列化復元中に、レコード標準コンストラクタが呼び出されてレコード・オブジェクトが構成されます。 readObjectやwriteObjectなどの特定の直列化関連メソッドは、直列化可能レコードでは無視されます。 詳細は、Javaオブジェクト直列化仕様セクション1.13、"レコードの直列化"」を参照してください。

導入されたバージョン:
1.1
外部仕様
関連項目: