Java 

以前のリリースでの
オブジェクト直列化の拡張機能

ドキュメントの目次
64K を超える文字列を直列化できる (1.3 以降)
1.3 より前は、64K を超える文字列を直列化しようとすると、java.io.UTFDataFormatException がスローされました。1.3 では、64K を超える文字列を直列化できるように、直列化プロトコルが拡張されました。ただし、1.2 以前の JVM で、1.3 に準拠した JVM で記述された長い文字列を読み込もうとすると、1.2 以前の JVM に java.io.StreamCorruptedException が返されます。

直列化のパフォーマンスの向上 (1.3 以降)
全般的なパフォーマンスを向上させるため、直列化にいくつかの変更が加えられました。
  • 不要なメモリ割り当ておよび同期/メソッド呼び出しのオーバーヘッドを減らすために、UTF 文字列の読み取り/書き込みが最適化されました。
  • プリミティブデータ配列の読み取りおよび書き込み用のコードが簡素化されました。ネイティブメソッドの呼び出し回数を最小にするため、float および double 型配列の読み取り/書き込みが再実装されました。
  • 内部バッファリングが改善されました。
  • 異なるネイティブメソッドの呼び出し回数を最小にするため、プリミティブフィールド値の取得/設定用リフレクション操作がバッチ化されました。

例外報告の改善 (1.3 以降)
直列化復元のクラス解決処理中にクラスが検出されなかった場合は、汎用的な例外ではなく、元の java.lang.ClassNotFoundException がスローされるようになりました。この結果、エラーについて詳細な情報を得られるようになりました。また、直列化復元の例外では、直列化復元中の上位クラスが報告されていましたが、検出されなかった実際のクラスの名前が保存されて報告されるようになりました。たとえば、RMI 呼び出しを行うと、スタブクラスは検出されるが、リモートインタフェースクラスが検出されないことがあります。この場合、現在の直列化機構では、検出されなかったクラスがそのインタフェースクラスであると正しく報告され、スタブクラスが検出されなかったという誤った報告は行われません。

java.io.ObjectOutputStream.writeClassDescriptor
java.io.ObjectInputStream.readClassDescriptor (1.3 以降)
java.io.ObjectStreamClass クラス記述子の直列化表現をカスタマイズする方法を提供するため、writeClassDescriptor メソッドと readClassDescriptor メソッドが追加されました。java.io.ObjectStreamClass のインスタンスの直列化が必要なときには、writeClassDescriptor が呼び出されます。また、writeClassDescriptorObjectStreamClass を直列化ストリームに書き込みます。逆に、直列化ストリーム内の次の項目として、ObjectInputStreamObjectStreamClass インスタンスを要求している場合は、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 節を参照してください。

javadoc ツールタグ @serial@serialField、および @serialData (1.2 以降)
クラスの直列化形式をドキュメント化する手段を提供するために、javadoc タグ @serial@serialField および @serialData が、追加されました。javadoc は、これらのタグの内容を基にして直列化の仕様を生成します。詳細は、「Java オブジェクト直列化仕様」の 1.6 節を参照してください。

プロトコルのバージョン管理 (1.2 以降)
1.2 より前は、オブジェクト直列化で使用するプロトコルには、java.io.Externalizable インタフェースを実装するオブジェクトのクラスを使用できない場合に、そのオブジェクトをスキップする機能はありませんでした。1.2 では、この欠陥を解決する新たなプロトコルバージョンが追加されました。下位互換性を確保するため、ObjectOutputStream および ObjectInputStream は、新旧どちらのプロトコルで書き込まれた直列化ストリームに対しても、読み取りおよび書き込みが可能です。使用されるプロトコルバージョンは、ObjectOutputStream.useProtocolVersion メソッドを呼び出すことにより選択できます。 互換性に関する問題の詳細は、「Java オブジェクト直列化仕様」の 6.3 節を参照してください。

クラス定義された writeReplace および readResolve メソッド (1.2 以降)
1.2 以降、クラスは、writeReplace および readResolve メソッドを定義できるようになりました。これらのメソッドを使用することにより、指定されたクラスのインスタンスは、直列化および直列化復元時にそのインスタンス自体の置換を指定できます。これらのメソッドに必須の署名、および詳細については、「Java オブジェクト直列化仕様」の 2.5 節および 3.6 節を参照してください。

java.io.ObjectOutputStream.writeObjectOverridejava.io.ObjectInputStream.readObjectOverride (1.2 以降)
1.2 以降、ObjectOutputStream および ObjectInputStream のサブクラスは、writeObjectOverride および readObjectOverride メソッドをオーバーライドすることにより、カスタム直列化プロトコルを実装できます。これらのメソッドが呼び出されるのは、ObjectOutputStream/ObjectInputStream サブクラスがアクセス権 java.io.SerializablePermission("enableSubclassImplementation") を保持し、ObjectOutputStream/ObjectInputStream の引数を持たないコンストラクタを呼び出す場合だけです。詳細は、「Java オブジェクト直列化仕様」の 2.1 節および 3.1 節を参照してください。

セキュリティアクセス権のチェック (1.2 以降)
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 節を参照してください。

クラスの直列化可能フィールドの定義 (1.2 以降)
デフォルトでは、直列化可能クラスのインスタンスを直列化する際に、その直列化可能クラスのすべての非 static および非 transient フィールドの値が書き込まれます。1.2 では、クラスからこの処理をより細かく制御することのできる機構が導入されました。特別なフィールドである serialPersistentFields を宣言することにより、直列化可能クラスは、クラスまたはサブクラスのインスタンスの直列化時に書き込まれるフィールドを決定できます。この機能により、クラス内の実際のフィールドに直接関連しない直列化可能フィールドを、クラスから「定義」できるようにもなりました。この機能を次に説明する直列化可能フィールド API とともに使用することにより、クラスの直列化表現を変更せずに、クラスに対しフィールドを追加または削除できます。詳細は、「Java オブジェクト直列化仕様」の 1.5 節および 1.7 節を参照してください。

直列化可能フィールド API (1.2 以降)
1.2 で導入された直列化可能フィールド API を使用すると、クラス定義の writeObject/readObject メソッドから、直列化可能フィールドの値を、名前と型によって明示的に設定して取得できます。クラスに以前のクラスバージョンとの下位互換性が必要な場合は、この API は特に有用です。これは、クラスによっては、現在のクラスに直接マッピングできない一連の直列化可能フィールドを以前のバージョンで定義しているものがあるためです。この場合、新規バージョンのクラスでカスタムの writeObject および readObject メソッドを定義します。これらのメソッドは、(新規) クラスの指定されたインスタンスの内部状態を「以前の」直列化形式に変換できます。また、その逆も可能です。詳細は、「Java オブジェクト直列化仕様」の 1.7 節を参照してください。
* この Web サイトで使用されている「Java 仮想マシン」または「JVM」という用語は、Java プラットフォーム用の仮想マシンを表します。
Copyright © 1999 Sun Microsystems, Inc.All Rights Reserved.
コメントの送付先:rmi-comments@java.sun.com 
Sun