Object(Out/In)putStreamの使い方

ObjectをシリアライズしてStreamに流してくれる非常に便利なObjectOutputStreamとObjectInputStreamなんですが、Java Docを読んでも出てこない部分とか分かりにくい部分が多すぎる。

http://ameblo.jp/dione/entry-10034526994.html
http://d.hatena.ne.jp/tondol/20081002/1222879470
上記のサイトで指摘されているように最終的にはreset()を呼び出す必要があるんだけど、
ソース読んで分かったことをちょっと書いておく。

用途によってwriteObjectとwriteUnsharedを使い分ける

writeObjectは全く同じObject(メモリ上で同じもの)を送受信すると、
キャッシュされているインデックスだけを送受信するので実際には帯域が使用されない。
なので、エミュレーションを行う上でメモリを節約したいが帯域は消費したいなんて時にはwriteUnsharedを使う。
equalsとかhashcodeをオーバーライドしてても関係ないっぽい。メモリ上のhashcode(System.identifyHashcode(obj))を使ったり、わざわざ==を使ったりしてる。
まぁ意味はわからんでもない。

writeUnsharedを呼び出してもキャッシュはされる

ところが、writeUnsharedを呼び出すとキャッシュの部分にnullが代入されたり、
readUnshared側でもデフォルトの空っぽオブジェクトを代入したりするソースになってるように見えるのだが、
じっくりソースを追っかけるとどうやらこの機能は完全ではなく、
オブジェクトを受け取る時の動作のところどころにキャッシュに代入するようなことが書かれてある。なぜか。
てことで、Unsharedはトラフィックを増やすような目的以外では使えない。
使いもしないのになんでキャッシュに突っ込んでるんだろうなぁ。
writeUnsharedで送ったオブジェクトはwriteObject側でも参照されないのに。(これはJava Docにも書いてある)

解決策

てことで、定期的にreset()メソッドを呼び出すのがやっぱり正しい実装のようです。
reset()を呼び出すとキャッシュの中身が全部nullになって、sizeも0にリセットされます。確かにこれでキャッシュは空っぽになるのでメモリ的には大丈夫。
で、定期的の定期ってどれぐらいよ、っていうのがよくわかりません。
readUnsharedを常に呼び出す実装であれば毎回呼べばいいと思うんだけど、
そうでない場合っていつ呼び出すのが正しいんだろう。
そもそもキャッシュってのは回数を重ねる毎に効いてくる訳で、
ある程度回数を重ねたのにリセットしてたら意味が無い。
そもそもreset()しか出来ないのが問題で、gc()みたいなメソッドがあるべきなんだよね。
Object(Input/Output)Stream内に独自のGCっていうかただのスタックでもいいから持ってる方がいいんじゃないか、と。
で、先頭n個を残してclearとかね。
Java側が明示的にリフレッシュする必要はないとしても、こっち側でリフレッシュできるようにしといてくれないと、はっきり言ってキャッシュの意味がない。


そのうちSunが直してくれるのを期待するしかないかな。