たぷつきません

おなかがでてきた。もうたぷついてるやん。

メモリリーク

 S2TestCaseでテストケースごとに使用メモリが増えて、どんどん遅くなり最後は固まるという現象が起きた。現行プロジェクトの開発メンバー3人がかりでいろいろ調査したところS2自体S2Daoメモリリークしていることが判明。もろ循環参照で、S2ContainerImplのdestroyでは全く解放されない。S2ContainerImpl,S2ComponentDefImpl,MetaDataDef,AOPなんたらクラスなどの間で循環参照が起きているので1つ1つ解きほぐす必要が。2ちゃんでも比較的最近(2006/05/01)メモリリークの問題が書かれているようだが、議論にもなっていない。2ちゃんだからガセ扱いされてしまっているのではないだろうか。実は対策は進んでいるのだろうか。昔からこうだったのだろうか。と疑問は尽きない。
 destroyというきっかけは提供されているのだからコアの4〜5クラス程度の修正で対策は可能に見える。ただあくまでも「今日ざっくりと追ってひとまずS2ContainerImplへパッチをあてていったところでは」の範囲での話。最も中心のところでこれでは全体の設計としてメモリリークが考慮されていない可能性が高いと思われるので、1つ潰してはまたその次が出現しそうだ。HotDeployといった機能も提供しているのだから、正しくリロードできないのは結構致命的ではなかろうか。まずは開発プロジェクト内で対策して、どこかのタイミングで、seasar2 projectにフィードバックできるのではないかと思う(もちろんその前にバグフィックスされたものがリリースされるほうが助かるのだが)。
 heap_diagnosticsでリークを追っていて気づいたのだが、Containerインスタンス1つにつきServlet系のスコープ全てが立ち上がる。1ダイコン辺りで1Containerが出来てその度に付随するオブジェクトインスタンスが1セット出来る。現行プロジェクトではダイコンの数が多かったのでものすごいインスタンス数になっていた。これらのスコープ用オブジェクトは、1ダイコンごとでは使用しない可能性の方が高いと思われるので、ServletContext,Request,ResponseのスコープはLazyにインスタンス化するのが望ましいだろう。現状はパフォーマンス的に良い実装ではない。
 道理でWebアプリのリロードでOutOfMemoryになるわけだ。リリース後に発覚するなんてことがなく開発中の段階で気づけたことは結果的に良かった(といってもこれまで過去にリリースしたものはアウトなわけだが)。

SimpleDateFormat

 スレッドセーフじゃないことを騒いでるような文書がありますけど、問題はドキュメント化うんぬんじゃないでしょう。こちらの情報は実験とかしているけどソース見れば一発で分かるんで実験するまでもない。calendar というフィールドを持っちゃっていて、format(date) のdateがそのままこのフィールドにsetTimeしてから処理が始まるので当然スレッドセーフじゃないわけです。
 で、確かに実装にどうだろう感があるわけですが、「Simple」「単純な」と自明なんだから鬼首とったかのような表現の方がどうだろう(前者の方ね)。calenderというプロパティがある時点で怪しいし。
むしろ問題はSimpleDataFormatよりも、DateFormatの方が悪しき存在です。getInstance というファクトリメソッドになっているにも拘らず、その中を辿っていくと、もろ「new SimpleDateFormat(...)」 と直書きしているという…。なんの意味も無いじゃん。これがjava標準かと思うと泣けてくるわけです。
 しかもgetInstanceは、getDateTimeInstance、さらにgetというメソッドを使っていて、この3つ全てがpublic staticなんです。abstract classであるにも拘らず3つも名前資源を食いつぶしています。継承クラスのことを考えとらん。
 これが、インスタンス化手順を共通化したDateFormat継承クラス(もしくはインスタンス化するファクトリ)をDateFormatに対して registDefaultDateFormat(もしくはregistDefaultDateFormatFactory)できさえすれば良いんですけどね。