6
3

More than 5 years have passed since last update.

@ViewScopedにメモリを喰い潰された話

Last updated at Posted at 2019-07-05

環境

Webアプリケーション

  • Java 8
  • Java EE 7 (Payara 4)
  • JSF 2.2

現象

OutOfMemoryでアプリケーションが死んだ。
閉じた画面の管理Beanがずっと生存しててR.I.P.

怪しい部分

  • セッションタイムアウト時間が長い
  • 一部管理ビーンがメモリ喰う

当初の流れ

よくある説明

アノテーション 名前空間 生存期間
@RequestScoped javax.enterprise.context.RequestScoped 1回のHTTPリクエスト/レスポンス
@ViewScoped javax.faces.view.ViewScoped ビューが同じである間
@SessionScoped javax.enterprise.context.SessionScoped セッション開始~終了
@ApplicationScoped javax.enterprise.context.ApplcationScoped アプリケーションが起動している間
@Dependent javax.enterprise.context.Dependent インジェクトされた先のスコープに依存
@ConversationScoped javax.enterprise.context.ConversationScoped 開始と終了を任意に指定できる
@FlowScoped javax.enterprise.context.FlowScoped あらかじめ定義したフローの開始から終了まで

自分の理解

ほ~ん。
@ViewScopedは画面開いたら生成して、閉じたら廃棄してくれるんか便利。
@SessionScopedにログインユーザーの情報持たせて、@ViewScopedで業務画面作ればいいんだな。

web.xmlでセッションが保持するView数も指定できると。

/web.xml
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>sever</param-value>
    </context-param>
    <context-param>
        <param-name>com.sun.faces.numberOfLogicalViews</param-name>
        <param-value>20</param-value>
    </context-param>
    <context-param>
        <param-name>com.sun.faces.numberOfViewsInSession</param-name>
        <param-value>20</param-value>
    </context-param>

上限超えたら解放されるんか把握。

とかやってたら、破棄されたはずの@ViewScopedの管理ビーンがめっちゃ生存しててメモリが圧殺された。

実際

どうやら以下のパターンでないと@ViewScopedの管理ビーンは解放されないらしい。

  • 結果が得られないポストバック
  • セッションの有効期限切れ

だから以下のパターンでは生存する。

  • 別のページへのGET
  • ページ更新
  • セッション内の最大論理ビュー数を超えたとき (期限切れになるけど破棄されない)

解決策

標準の@ViewScopedじゃなくてOmniFaces @ViewScopedを使う。
OmniFaces@ViewScopedアノテーション使うだけで、ブラウザのunloadイベントを拾ったら解放してくれる。
デフォルトの依存関係になるべく影響を与えないように作られてるので@ViewScoped使うためだけにでも導入していいかなと。

あとがき

Viewっていわれると画面単位に管理してくれるのかなと安直に考えちゃったけど、そもそも画面単位じゃなくてコンポーネントツリー単位だから画面閉じたら解放してくれるとか期待するのが間違ってるよねって話。

最大論理ビュー数を超えても破棄されないのは罠な挙動だけど。

そもそもセッション長く保持するな&巨大にするな

参考文献

jsf-2 – セッションが期限切れになるまで期限切れの@ViewScoped Beanが破棄されない理由
stack overflow : JSF 2.2 Memory Consumption: Why does Mojarra keep the ViewScoped Beans of the last 25 Views in Memory?

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3