0

キューからメッセージを消費し、ステートレス EJB を呼び出していくつかのデータベース操作を実行する MDB があります。このようなもの:

public class TestMDB implements MessageListener
{
  @EJB
  private UpdateService updateSvc;

  @Override
  public void onMessage(Message message) 
  {
    try
    {
      updateSvc.updateSystemStatuses();
    }
    catch(Exception e)
    {
      // log error
    }
  }
}

上記のコードで updateSystemStatuses() 呼び出しが RuntimeException をスローすると、メモリ リークが発生するようです。updateSystemStatuses() で RuntimeExceptions をスローするように誘導することでプロセスを高速化しました。これが発生すると、CPU 使用率とメモリ使用率が急上昇します (JVisualVM で見られるように)。OutOfMemoryErrors が発生し始めるまで続きます。

onMessage から RuntimeExceptions をスローするようにコードを変更すると、リソース リークは完全になくなるようです。

public class TestMDB implements MessageListener
{
  @EJB
  private UpdateService updateSvc;

  @Override
  public void onMessage(Message message) 
  {
    try
    {
      updateSvc.updateSystemStatuses();
    }
    catch(RuntimeException e)
    {
      //log error
      throw e;
    }
    catch(Exception e)
    {
      //log error
    }
  }
}

EJB メソッドから RuntimeException をスローするとトランザクションのロールバックが発生することは承知しており、これは私が見ていることと関係があると思いますが、それ以上に何が起こっているのかはわかりません。リソース リークは Glassfish のバグですか? MDB で例外を正しく処理していますか?

Eclipselink と Oracle 11G を使用して、Java 1.6.0_35 で Glassfish 3.1.2.2 を実行しています。

4

1 に答える 1

0

あなたは「有害なメッセージ」の状況に直面していると思います。MDB はキュー内のメッセージをフェッチし、それを処理しようとします。処理が失敗する (例外をスローする) ため、メッセージはキューに戻されます。そして、何度も何度も処理されます。これが、CPU が天井を突き破るのを見る理由です。

Glassfish では、無視されるまで (つまり、処理で例外がスローされた場合) にメッセージを処理できる回数を指定できます。このブログで役立つ情報を見つけることができます。

http://weblogs.java.net/blog/felipegaucho/archive/2009/09/24/handling-poison-messages-glassfish

于 2012-10-21T20:08:23.307 に答える