メモリー管理に失敗したJavaアプリの実例

2011年3月11日(金)
東 浩二(A-pZ)(監修:山田祥寛)

O/Rマッピング・ツールと運用設計ミス

本稿では、Java EEアプリケーションで使われることの多いO/Rマッピング・ツールにおけるサイジングの重要性について解説します。

今回取り上げる事例は、JavaのWebアプリケーション開発ではかなり有名なO/Rマッピング・ツールである「iBatis」*1を使ったものです。

問題となったアプリケーションでは、データベースの接続からクエリーを投げるところまで、全面的にiBatisを利用していました。採用された理由は、既存のSQLを利用しつつ、動的SQLを簡単に作成できるところでした。初回リリース後しばらく経過しても、特に大きな問題もなく、システムは順調に利用されていました。

その後、機能改善と追加機能の要望が挙がりました。システムは安定稼働しているので、拡張しても問題ないだろうと判断して改修することになりました。この際に、定期バッチ処理で使っていた一括検索処理を一部、Webアプリケーションへ移行することになりました。

この検索処理は、定期的にデータベースから特定期間のデータをCSVで出力するものです。このバッチ側ではiBatisは利用していませんでしたが、SQLの部分は、ほぼそのままWebアプリケーションへ移植することができました。

図1: アプリケーションの機能を改修した事例

図1: アプリケーションの機能を改修した事例

テスト時には、特に問題もなく動作していたので、そのままリリースすることになったのですが、しばらくした後、問題が発生します。

ある日、Webアプリケーションへ移行した一括検索処理を実行すると、とある条件に限ってシステムが停止するとの報告を受けます。ログを調べてみると、OutOfMemoryが発生しており、そのエラーはiBatisを使った検索処理にて発生していました。

しかしこれは、かつてバッチ処理で実装していたときには、問題がなかった条件です。偶発的なものなのかどうかを調査するため、数回同じように処理をさせましたが、かなりの確率で同じエラーとなります。

障害を細かく追跡し、たどり着いた問題のコードは、以下のようなものでした。

これは、通常のiBatisの利用方法です。しかし実際には、この通常の利用方法が大問題です。問題を引き起こした原因は、以下の条件が重なった結果でした。

  • システム改修のタイミングで、他システムからのデータが大量に追加された
  • このコードをWebアプリケーションに移植した際の、単体機能のテストでは問題がなかった
  • システム改修後、複数のユーザーが同時に処理を行う運用に変わっていた

結果、検索結果となるListは、数万件のレコードをそのままオブジェクトへ展開することになり、それはそのまま、一時的ですがメモリーを消費します。それが複数ユーザーが同時利用することにより、設定していた最大ヒープ・メモリーのサイズを超えてしまったため、システムダウンとなったのです。これらの問題は、当初想定された条件とは異なるものです。

これは、想定されるデータ・サイズの見積もりミスとも言えますし、利用条件のミス・マッチとも取れますし、追加要件に対応したコードになっていないとも考えられます。

しかし、システム稼働後には、ヒープ・サイズの変更もできず、ハードウエアの増設も簡単にはできません。このような状況になった場合、どのように対応するのが望ましいのでしょうか。

著者
東 浩二(A-pZ)(監修:山田祥寛)
WINGSプロジェクト

有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表:山田祥寛)。おもな活動は、Web開発分野の書籍/雑誌/Web記事の執筆。ほかに海外記事の翻訳、講演なども幅広く手がける。2011年3月時点での登録メンバは36名で、現在もプロジェクトメンバーを募集中。執筆に興味のある方は、どしどしご応募頂きたい。著書多数。
http://www.wings.msn.to/

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています