2018年9月21日金曜日

【Java】「OutOfMemoryError」で親スレッドダウン【cron4j】

当然といえば当然ですが、落ちます。Tomcatは落ちずに画面は使えているので気付きづらいのですが(いや、OutOfMemoryなんてすぐに気づくべきですよね。)、定期処理が動かなくなっていて、何かと調べていたらOutOfMemoryErrorが出ていました。

cron4jについて詳しく調べてなくて、間違いがあったらすみません(時間があったら、調べます)。cron4jには親スレッド※1がいるみたいですね。jstackでみるとtimerと言う名のスレッドが存在します。たぶんこのtimerスレッドが親で、登録されている時刻になると子スレッドを生成(scheduleという名のスレッド)して、処理を行わせるのでしょう。

ということは、極、すごーく簡単に書くと親スレッドが動いているコードは以下のようになっていると思われます。
で、ExceptionはOutOfMemoryをキャッチしない※2ので、このスレッドはアボートしてしまうってことだと思います。

while (runFlg ) {
  try {
    if (定期時刻を満たした) {
      処理を実行
    }
  } catch (Exception ex) {
     :
  }
}

人命に関わるシステムでなければ、落ちた方が良いと言う考え方がありますが、落ちたほうが良いんですかね?Tomcatは生きているので、cron4jは落ちたけど、画面は生きているって状態になってしまって統一性が無い状態になってしまいますが。
そもそもOutOfMemoryを監視するようになってないのがまずいのでしょうが。

※1 呼び方は私が勝手に言ってますので、本来の名前があるはずで、timerスレッド?かもしれません。
※2 Javaの例外処理では、トップにThrowableがいて、Throwableを継承したErrorクラスとExceptionクラスに分かれます。catch (Exception ex)と書いた場合、Errorの子クラスであるOutOfMemoryはcatchできません。

0 件のコメント:

コメントを投稿