8

Java では、シリアル化により、ストリームへのオブジェクトの読み取りと書き込みが非常に簡単になります。たとえば、次のコード スニペットだけで、オブジェクトをストリームに書き込むことができます。

ObjectOutputStream oos = ... //Initialize your output stream
Object toWrite = ...         //Initialize what you want to write here
oos.writeObject(toWrite);    //Writes the object to the stream
oos.flush();

のクラスがインターフェイスをtoWrite実装し、すべての非メンバー変数も である場合、これは問題なく機能します。つまり、参照を介して送信しようとしているオブジェクト階層全体が. このコードの唯一の問題は、内部の何かがそうではないことだと仮定します。SerializabletoWritetransientSerializabletoWriteSerializabletoWriteSerializable

階層が完全Serializableではない場合、 への呼び出しは をoos.writeObject(toWrite)スローしjava.io.NotSerializableExceptionます。問題を迅速に解決するために必要なすべてが例外によって提供されるわけではないことを除けば、これで問題ありません。シリアル化できなかったクラスがわかります。スタック トレースは次のようになります。

java.io.NotSerializableException: some.package.and.ClassIDidntExplicitlyReference
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    ...
    at my.package.MyClass.codeThatWroteTheOffendingObject(MyClass.java:###)

この種のポイントは正しい方向を示していますが、 によって参照される深いオブジェクト階層が関係する場合toWrite、問題のあるクラス参照がどこから来たのかが常に明確であるとは限りません。のインスタンスに代入toWriteし、のMyClassインスタンスに、 ではないのインスタンスに設定されたMyClassというメンバー オブジェクト参照があるとします。次のようなものが印刷されていることを確認したいと思います。nonSerializableReferenceClassIDidntExplicitlyReferenceSerializable

my.package.MyClass.nonSerializableReference instanceof some.package.and.ClassIDidntExplicitlyReference

この問題にはおそらく迅速な解決策がなく、リフレクションの使用が必要になる可能性が高いことはわかっています。ここSOの誰かが以前にこれを行ったことがありますか?もしそうなら、あなたの洞察を共有していただけませんか?

答え

結局、リフレクションFieldModifierクラスを使用してパスを見つけました。残念ながら、(会社のポリシーに反して) 私のコードを共有することはできませんが、私の出力をお見せすることはできます。クラス A は B のインスタンスを保持し、B は C のインスタンスを保持し、C は D のインスタンスを保持します。すべてSerializableD を除きます。パスを見つけるために深さ優先検索を使用することになりました。

A.b -> 
  B.c -> 
    C.d instanceof class D

一時的にするC.dと、検索で結果が得られません。かなりクール!

4

3 に答える 3

1

これは奇妙な質問です。コンパイル時に何をすべきかを実行時に決定したいのです。理論的には、オブジェクトへのパス重要ではありません。コードを修正するには、シリアル化できないものを参照するオブジェクトを見つける必要があります。

とはいえ、リフレクションを使用して単純な再帰ツリー クローラーを作成することもできます。そうは言っても、入ってくるオブジェクトを適切にログに記録する独自の ObjectInputStream を実装することでうまくいくかもしれません。詳細については、ソースを参照することをお勧めします

于 2012-12-06T00:40:57.023 に答える