2016-05-19 10 views
1

私はJavaプロジェクトでキャッシュとしてaerospikeを使用しています。 キャッシュされたオブジェクトのパッケージを変更しました。 私は1台のマシンに新しいコードを導入しました。古いキャッシュオブジェクトがキャッシュに存在するため、シリアル化例外を取得します。Javaクラスのパッケージを変更した場合。古いシリアル化されたバージョンからの直列化解除はまだ機能しますか?

いくつかのマシンで古いコードを実行し、いくつかのマシンで新しいコードを実行して、両方をAerospikeキャッシュのオブジェクトを取得/配置できるようにする必要があります。

これを達成する方法はありますか? なぜこの例外が発生するのですか?

+0

[このリンク](http://stackoverflow.com/questions/30795262/redis-serialization-and-deserialization)は、クラスのserialVersionUIDを定義する必要があります。 –

答えて

0

クラスが属するパッケージは、そのクラスの完全修飾名の一部であるパッケージ名に反映されるように、そのクラスの基本情報の基本的な部分です。すべての実際の目的と目的のために、クラスが割り当てられているパッケージを変更すると、元のクラスが削除され、完全に異なるクラスに置き換えられます。

特に、Javaシリアル化を使用して "my.package.MyClass"という名前のクラスのインスタンスをシリアル化すると、結果を正常にデシリアライズすると、常に "my.package.MyClass"という名前のクラスのインスタンスが生成されます。そのようなクラスをロードできない場合や、ロードされたクラスのシリアライゼーション・バージョンがシリアライズされたクラスのシリアライズ・バージョンと一致しない場合は、デシリアライゼーションは失敗します。

新しいクラスと一緒に古いクラスを保持している場合は、新しいバージョンのアプリケーションで逆シリアル化の問題を修正することができます。古いクラスのオブジェクトを準備して、それらを逆シリアル化するとすぐに新しいクラスのインスタンスに変換してください。しかし、新しいバージョンのアプリケーションを古いものと一緒に使いたい場合は、新しいクラスが影響を受けたクラスのオブジェクトをシリアル化するときに逆も行う必要があります。そうしないと、古いアプリケーションに逆シリアル化エラーが発生します。この時点で、パッケージ名の変更がすべて重要であるかどうかを検討する必要があります。

全体として、Javaのシリアル化は、オブジェクトの格納にはあまり適していません。主にオブジェクトの通信を対象としています。少なくとも、キャッシュとコンシューマの間を動かすことができるXML、JSON、またはYAMLベースのシリアル化フォーマットに切り替えることを検討することもできます。このような変更はもちろん、古いバージョンのアプリケーションとは互換性がありませんが、すでに実行したパッケージの変更は明らかです。

0

は、一般的には直列化アルゴリズムは、次の処理を行います

  • これは、インスタンスに関連付けられたクラスのメタデータを書き出します。
  • java.lang.objectが見つかるまで、スーパークラスの説明を再帰的に書き出します。
  • メタデータ情報の書き込みが終了すると、インスタンスに関連付けられた実際のデータで開始されます。しかし今回は、最上位のスーパークラスから始まります。
  • インスタンスに関連付けられたデータを、最小のスーパークラスから最も派生したクラスに再帰的に書き込みます。

デシリアライゼーション中に、クラスの再インスタンス化を試みますが、パッケージ名が変更されているため、メタデータ内で指定されたクラスを見つけることができず、失敗します。

jDeserializeツールを見る価値があるかもしれません。ストリームに記述されているクラスはインスタンス化されません。代わりに、型、インスタンス、および値の中間表現を構築します。このため、ストリームを生成したクラスコードにアクセスすることなくストリームを分析できます。

関連する問題