目次 | 前の項目 | 次の項目 Java オブジェクト直列化仕様


A.6 非共有の直列化復元されたオブジェクトの保護

クラスが private または package private のオブジェクト参照フィールドを保持し、かつそのクラスが、それらのオブジェクト参照はクラス (またはパッケージ) の外部では利用できないという事実に依存する場合は、防衛のために、直列化復元プロセスの一環として参照オブジェクトをコピーするか、または ObjectOutputStream.writeUnshared メソッドと ObjectInputStream.readUnshared メソッド (JavaTM 2 SDK, Standard Edition バージョン 1.4 で導入) を使って内部オブジェクトへの一意参照を保証する必要があります。

コピーする方法では、ストリームから直列化復元されるサブオブジェクトを、「信頼されない入力」として扱う必要があります。新たに作成したオブジェクトを初期化して、直列化復元されたサブオブジェクトと同じ値を保持させ、readObject メソッドを使ってサブオブジェクトの代替とする必要があります。たとえば、オブジェクトが private バイト配列フィールド b を保持する場合、次に示すように、このフィールドを private のままにしなければなりません。

    private void readObject(ObjectInputStream s)
        throws IOException, ClassNotFoundException
    {
        s.defaultReadObject();

        b = (byte[])b.clone();

        if (<invariants are not satisfied>)
            throw new java.io.StreamCorruptedException();
    }
この問題は、可変サブオブジェクトへの内部参照 (private) を含む不変オブジェクトの直列化を考慮する際に特に重要です。コンテナオブジェクトの直列化復元時に、サブオブジェクトをコピーするための特別な措置が何もとられない場合、直列化ストリームへの書き込み権限を持つ悪意のある第三者が、可変サブオブジェクトへの参照を偽造し、これらの参照を使ってコンテナオブジェクトの内部状態を変更することで、コンテナオブジェクトの不変性を侵害する場合があります。このような場合に備えて、不変のコンテナクラスがクラス固有の直列化復元メソッドを提供することがポイントです。直列化復元される各可変コンポーネントオブジェクトのプライベートなコピーの作成は、このメソッドを使って行います。不変性を維持するために、不変コンポーネントオブジェクトのコピーを作成する必要はないことに留意してください。

また、clone の呼び出しが、常にサブオブジェクトを自己防衛的にコピーする正しい方法とは限らないことに留意することも重要です。独立したコピーを作成するため (およびコピーへの参照を「横取り (from stegword)」しないため) に clone メソッドをあてにできない場合、別の方法でコピーを作成する必要があります。サブオブジェクトのクラスが final ではない場合、呼び出される clone メソッドやヘルパーメソッドがサブクラスによってオーバーライドされる可能性があるため、常に別の方法でコピーを作成する必要があります。

JavaTM 2 SDK, Standard Edition バージョン 1.4 以降では、ObjectOutputStream.writeUnshared メソッドと ObjectInputStream.readUnshared メソッドを使って、直列化復元されたオブジェクトへの一意参照を保証することもできます。この方法では、防衛的にコピーする方法の複雑さ、パフォーマンスコスト、およびメモリオーバーヘッドの問題を回避できます。readUnshared メソッドと writeUnshared メソッドの詳細は、「3.1 ObjectInputStream クラス」および「2.1 ObjectOutputStream クラス」を参照してください。



目次 | 前の項目 | 次の項目
Copyright © 1997-2001 Sun Microsystems, Inc. All Rights Reserved.