ここでは、Java™ SE Development Kit 6 (JDK) 以前に行われた直列化の拡張機能について説明します。現行リリースでの拡張機能については、「Java SE Development Kit 6 での直列化の変更と拡張」を参照してください。
Enum.valueOf
メソッドが呼び出されます。ObjectInputStream.readClassDescriptor
メソッドによってスローされる ClassNotFoundException
は、StreamCorruptedException
として ObjectInputStream.readObject
のトップレベルの呼び出し側に反映され、その原因は空であることだとされました。現在は、InvalidClassException
としてトップレベルの呼び出し側に反映されるようになり、その原因は元の ClassNotFoundException
となります。ObjectStreamClass.lookup
メソッドの Class
引数で表されるクラスの静的初期化子内で、このメソッドが呼び出された場合にデッドロックする可能性がありました。この場合、デッドロックが発生することはなくなりました。Serializable
インタフェースの javadoc が拡張され、serialVersionUID
の役割と使用方法をさらに詳細に指定できるようになり、また、直列化可能なクラスの serialVersionUID
を明示的に指定する必要性が明確となりました。これらの API は、含まれる配列オブジェクトをセキュアな方法でより効率的に読み取るために使用できます。『Java オブジェクト直列化仕様』のセクション A.6「非共有の直列化復元されたオブジェクトの保護」を参照してください。
同様に、J2SE 1.4.0 から、ObjectInputStream.readFields または ObjectInputStream.readUnshared をオーバーライドするサブクラスで ObjectInputStream の引数を 1 つ取る public のコンストラクタを直接的または間接的に呼び出すときにも、"enableSubclassImplementation" SerializablePermission が必要になりました。
このような変更は、アプリケーションの大部分には影響がありません。ただし、putFields または readFields メソッドをオーバーライドするが直列化インフラストラクチャーの残りの部分はオーバーライドしない ObjectInputStream サブクラスや ObjectOutputStream サブクラスは影響を受けます。
private void readObjectNoData() throws ObjectStreamException;readObjectNoData() メソッドはクラス定義メソッド readObject() と似ています。ただし、定義されていれば、直列化復元中のオブジェクトのスーパークラスのクラス記述子およびそのクラス記述子で記述されるオブジェクトデータが、直列化ストリームにない場合に呼び出されるという点が異なります。つまり、次のとおりです。クラス C のオブジェクト O が直列化復元中で、O を直列化復元している VM 内の C のスーパークラスが S である場合、O の直列復元中に ObjectInputStream によって S.readObjectNoData() が呼び出されるのは、次の条件が成立する場合だけです。
詳細は、ObjectInputStream の API 仕様でクラスの説明を参照してください。
java.io.UTFDataFormatException
がスローされました。1.3 では、64K を超える文字列を直列化できるように、直列化プロトコルが拡張されました。ただし、1.2 以前の JVM で、1.3 に準拠した JVM で記述された長い文字列を読み込もうとすると、1.2 以前の JVM は java.io.StreamCorruptedException
を受け取ります。java.lang.ClassNotFoundException
がスローされるようになりました。この結果、エラーについて詳細な情報を得られるようになりました。また、直列化復元の例外では、直列化復元中の上位クラスが報告される代わりに、検出されなかった基のクラスの名前が保存されて報告されるようになりました。たとえば、RMI 呼び出しを行うと、スタブクラスは検出されるが、リモートインタフェースクラスが検出されないことがあります。この場合、現在の直列化メカニズムでは、検出されなかったクラスがそのインタフェースクラスであると正しく報告され、スタブクラスが検出されなかったという誤った報告は行われません。java.io.ObjectOutputStream.writeClassDescriptor
,java.io.ObjectInputStream.readClassDescriptor
(1.3 以降)java.io.ObjectStreamClass
クラス記述子の直列化表現をカスタマイズする方法を提供するため、writeClassDescriptor
メソッドと readClassDescriptor
メソッドが追加されました。writeClassDescriptor
は、java.io.ObjectStreamClass
のインスタンスの直列化が必要なときに呼び出され、ObjectStreamClass
を直列化ストリームに書き込みます。逆に、直列化ストリーム内の次の項目として、ObjectInputStream
が ObjectStreamClass
インスタンスを要求しているときは、readClassDescriptor
が呼び出されます。ObjectOutputStream
および ObjectInputStream
のサブクラスは、これらのメソッドをオーバーライドすることにより、クラス記述子をアプリケーション固有の形式で送信できます。詳細は、『Java オブジェクト直列化仕様』のセクション 2.1 および 3.1 を参照してください。java.io.ObjectOutputStream.annotateProxyClass
,java.io.ObjectInputStream.resolveProxyClass
(1.3 以降)ObjectOutputStream.annotateClass
および ObjectInputStream.resolveClass
に類似しています。ただし、これらのメソッドは、非プロキシクラスとは対照的に動的プロキシクラス (java.lang.reflect.Proxy
を参照) に適用される点が異なります。ObjectOutputStream
のサブクラスは、annotateProxyClass
をオーバーライドすることにより、カスタムデータを動的プロキシクラスの記述子とともにストリーム内に格納できます。ObjectInputStream
サブクラスは、次に resolveProxyClass
をオーバーライドすることにより、指定されたプロキシクラス記述子と関連付けるローカルクラスの選択にカスタムデータを利用します。詳細は、『Java オブジェクト直列化仕様』のセクション 4 を参照してください。@serial
、@serialField
、および @serialData
(1.2 以降)@serial
、@serialField
、および @serialData
が追加されました。javadoc は、これらのタグの内容を基にして直列化の仕様を生成します。詳細は、『Java オブジェクト直列化仕様』のセクション 1.6 を参照してください。java.io.Externalizable
インタフェースを実装するオブジェクトのクラスを使用できない場合に、そのオブジェクトをスキップする機能はありませんでした。1.2 では、この欠陥を解決する新たなプロトコルバージョンが追加されました。下位互換性を確保するため、ObjectOutputStream
および ObjectInputStream
は、どちらのプロトコルで書き込まれた直列化ストリームに対しても、読み取りおよび書き込みが可能です。使用されるプロトコルバージョンは、ObjectOutputStream.useProtocolVersion
メソッドを呼び出すことにより選択できます。互換性に関する問題の詳細は、『Java オブジェクト直列化仕様』のセクション 6.3 を参照してください。writeReplace
および readResolve
メソッド (1.2 以降)writeReplace
および readResolve
メソッドを定義できるようになりました。これらのメソッドを使用することにより、指定されたクラスのインスタンスは、直列化および直列化復元時にそのインスタンス自体の置換を指定できます。これらのメソッドに必須のシグニチャー、および詳細については、『Java オブジェクト直列化仕様』のセクション 2.5 および 3.6 を参照してください。java.io.ObjectOutputStream.writeObjectOverride
、java.io.ObjectInputStream.readObjectOverride
(1.2 以降)ObjectOutputStream
および ObjectInputStream
のサブクラスは、writeObjectOverride
および readObjectOverride
メソッドをオーバーライドすることにより、カスタム直列化プロトコルを実装できます。これらのメソッドが呼び出されるのは、ObjectOutputStream/ObjectInputStream
サブクラスがアクセス権 java.io.SerializablePermission("enableSubclassImplementation")
を保持し、ObjectOutputStream/ObjectInputStream
の引数を持たないコンストラクタを呼び出す場合だけです。詳細は、『Java オブジェクト直列化仕様』のセクション 2.1 および 3.1 を参照してください。ObjectOutputStream
および ObjectInputStream
のサブクラスは、継承したメソッドをオーバーライドすることにより、直列化プロセスの特定の局面への「フック」を取得できます。1.2 以降、オブジェクト直列化では、1.2 のセキュリティーモデルを使用して、サブクラスが特定のフックをオーバーライドするための適切なアクセス権を保持しているかどうかを確認しています。アクセス権 java.io.SerializablePermission("enableSubclassImplementation
") および java.io.SerializablePermission("enableSubstitution
") は、ObjectOutputStream.writeObjectOverride
メソッド、ObjectOutputStream.replaceObject
メソッド、ObjectInputStream.readObjectOverride
メソッド、および ObjectInputStream.resolveObject
メソッドが直列化の過程で呼び出されるかどうかを管理します。詳細は、『Java オブジェクト直列化仕様』のセクション 2.1 および 3.1 を参照してください。serialPersistentFields
を宣言することにより、直列化可能クラスは、クラスまたはサブクラスのインスタンスの直列化時に書き込まれるフィールドを決定できます。この機能により、クラス内の実際のフィールドに直接関連しない直列化可能フィールドを、クラスから「定義」できるようにもなりました。この機能を次に説明する直列化可能フィールド API とともに使用することにより、クラスの直列化表現を変更せずに、クラスに対しフィールドを追加または削除できます。詳細は、『Java オブジェクト直列化仕様』のセクション 1.5 および 1.7 を参照してください。writeObject
/readObject
メソッドから、直列化可能フィールドの値を、名前と型によって明示的に設定して取得できます。クラスに以前のクラスバージョンとの下位互換性が必要な場合は、この API は特に有用です。これは、クラスによっては、現在のクラスのフィールドに直接マッピングできない一連の直列化可能フィールドを以前のバージョンで定義しているものがあるためです。この場合、新規バージョンのクラスでカスタムの writeObject
および readObject
メソッドを定義します。これらのメソッドは、(新規) クラスの指定されたインスタンスの内部状態を「以前の」直列化形式に変換できます。また、その逆も可能です。詳細は、『Java オブジェクト直列化仕様』のセクション 1.7 を参照してください。