Javaシリアル化の最適な代替手段はどれですか?
-
04-07-2019 - |
質問
現在、これらのオブジェクトを後で回復できるように、あらゆる種類のオブジェクト(この実装には制御がありません)を保持する必要があるプロジェクトに取り組んでいます。
開発時にライブラリのユーザーを制限できないため、ORMを実装できません。
最初の選択肢は、Javaのデフォルトのシリアル化でシリアル化することでしたが、ユーザーが同じオブジェクトの異なるバージョン(属性の変更されたタイプ、名前など)を渡し始めたときに、オブジェクトを回復するのに多くの問題がありました。 / p>
XMLEncoderクラスで試してみました(オブジェクトをXMLに変換します)が、機能が不足していることがわかりました(たとえばEnumをサポートしていません)。
最後に、JAXBも試しましたが、これによりユーザーはクラスに注釈を付ける必要があります。
良い代替手段はありますか?
解決
あなたにとって最も簡単なことは、シリアル化IMOを使用することですが、クラスのシリアル化された形式(とにかく行うべきです)についてより多くの考えを入れてください。例えば:
- SerialUIDを明示的に定義します。
- 必要に応じて、独自のシリアル形式を定義します。
シリアル化されたフォームはクラスのAPIの一部であり、その設計には慎重に検討する必要があります。
これまで述べてきたことのほとんどは、Effective Javaに由来しているため、詳細については詳しく説明しません。代わりに、特にシリアル化に関する章を参照してください。実行中のすべての問題について警告し、問題の適切な解決策を提供します。
http://www.amazon.com/Effective-Java-2nd-Joshua- Bloch / dp / 0321356683
とはいえ、まだ非シリアル化アプローチを検討しているのであれば、ここにいくつかあります:
XMLマーシャリング
多くの人が指摘しているように、オプションはありますが、下位互換性に関しては同じ問題に直面するでしょう。ただし、XMLマーシャリングを使用すると、初期化中に一部のフレームワークがチェックを行う場合があるため、これらをすぐにキャッチできます。
YAMLとの変換
これは私がいじっていたアイデアですが、YAML形式(少なくともカスタムtoString()形式として)が本当に好きでした。しかし、実際には、唯一の違いは、XMLではなくYAMLにマーシャリングすることです。唯一の利点は、YAMLがXMLよりわずかに人間が読みやすいことです。同じ制限が適用されます。
他のヒント
2011年であり、商用グレードのREST Webサービスプロジェクトでは、次のシリアライザーを使用して、クライアントにさまざまなメディアタイプを提供します。
- XStream (XML用だがJSON用ではない)
- Jackson (JSONの場合)
- Kryo (高速でコンパクトなバイナリシリアル化形式)
- Smile (Jackson 1.6以降に付属のバイナリ形式)。
- Javaオブジェクトのシリアル化。
最近、他のシリアライザーを試しました:
- SimpleXML は安定しているように見え、XStreamの2倍の速度で実行されますが、状況。
- YamlBeans にはいくつかのバグがありました。
- SnakeYAML には日付に関する小さなバグがありました。
Jackson JSON、Kryo、およびJackson Smileはすべて、古き良きJava Object Serializationよりも大幅に高速で、約3倍から4.5倍でした。 XStreamは遅い側にあります。しかし、これらはすべて現時点では確実な選択肢です。他の3つは引き続き監視します。
http://x-stream.github.io/ はいいです。それを見ろ!非常に便利です
どの実装のコントロールがありません
解決策は、これをしないです。型の実装を制御できない場合は、シリアル化しないでください。物語の終わり。 Javaシリアル化は、タイプの異なるバージョン間のシリアル化の非互換性を管理するために、特にserialVersionUIDを提供します。実装を制御しないと、開発者がクラスを変更したときにIDが正しく変更されていることを確認できません。
「ポイント」の簡単な例を取り上げます。デカルト座標系または極座標系のいずれかで表すことができます。これらの種類の修正に動的に対処できるシステムを構築するのは非常にコストがかかります-シリアル化を設計するのはクラスの開発者でなければなりません。
要するに、間違っているのはデザインであり、テクノロジーではありません。
googleはバイナリプロトコルを考案しました- http://code.google.com/apis/ protocolbuffers / は高速で、XMLに比べてペイロードが小さくなっています。
プロトコルバッファの利点の1つは、C、C ++、python、javaと情報を交換できることです。
たとえば、 Gson でjsonへのシリアル化を試してください。
また、非常に高速なJDKシリアル化ドロップイン置換: http://ruedigermoeller.github.io/fast-serialization/
シリアル化の速度が重要な場合、JVMシリアライザーの包括的なベンチマークがここにあります:
個人的には、名声をよく使用します。Smalltalk(VWとSqueak)とPython。 (免責事項、私は名声プロジェクトの主な貢献者です。)
おそらくキャスター?
Betwixt は、オブジェクトをシリアル化するための優れたライブラリですが、自動ではありません。ものの。シリアル化する必要のあるオブジェクトの数が比較的固定されている場合、これはあなたにとって良いオプションかもしれませんが、「顧客」が常に新しいクラスをあなたに投げかけようとしている場合、それは価値がある以上の努力かもしれません(ただし、すべての特殊なケースでXMLEncoderよりも間違いなく簡単です。)
別のアプローチは、顧客に投げるオブジェクトに適切な.betwixtファイルを提供するように顧客に要求することです(これにより、それらに対する責任が事実上オフロードされます)。
長短:シリアル化は hard です-完全に脳死アプローチはありません。 Javaのシリアル化は、私がこれまでに見てきたような脳死の解決策に近いものですが、お気付きのように、バージョンuid値の誤った使用はそれを破ることができます。 Javaのシリアル化にはマーカー「シリアル化可能」インターフェースの使用も必要です。そのため、ソースを制御できない場合は、そのソースで運が悪くなります。
要件があなたが説明しているように本当に難しい場合、オブジェクト/アスペクト/何でも何らかのBCE(バイトコード変更)に頼らなければならないかもしれません。これは、小規模な開発プロジェクトの領域を超えて、Hibernate、Casper、またはORMの領域に移行しています...
別のアイデア:キャッシュを使用します。キャッシュにより、アプリケーションの制御、スケーラビリティ、堅牢性が大幅に向上します。ただし、シリアル化する必要がありますが、キャッシングサービスフレームワーク内で管理がはるかに簡単になります。キャッシュはメモリ、ディスク、データベース、アレイ、またはすべてのオプションに保持できます。一方はオーバーフロー、スタンバイ、他方はフェイルオーバーです。 Commons JCSとEhcacheは2つのJava実装であり、後者は最大32 GBのストレージが無料のエンタープライズソリューションです(免責事項:ehcacheでは動作しません;-))。
SBEは、高速のバイトバッファベースのシリアル化ライブラリ用の確立されたライブラリであり、バージョン管理が可能です。ただし、長さラッパークラスを記述する必要があるため、使用するのは少し難しいです。
その欠点を考慮して、最近、SBEとFIXプロトコル(トレード/クォートメッセージを交換するための一般的な金融市場プロトコル)に触発されたJavaのみのシリアル化ライブラリを作成しました。弱点。 https://github.com/iceberglet/anymsg
をご覧ください。