MDB异常处理中的明显资源泄漏

时间:2012-10-02 01:35:45

标签: glassfish ejb message-driven-bean

我有一个MDB,它使用来自队列的消息,然后调用无状态EJB来执行一些数据库操作。像这样:

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。

如果我修改代码以将RuntimeExceptions抛出onMessage,资源泄漏似乎完全消失了:

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。

1 个答案:

答案 0 :(得分:0)

我认为您正面临“毒药消息”的情况。您的MDB在队列中提取消息并尝试处理它。由于处理失败(抛出异常),消息将被放回队列中。然后又一次又一次地处理。这就是为什么你看到CPU通过屋顶。

使用Glassfish,您可以指定在忽略之前处理消息的次数(即,如果处理引发异常)。您可以在此博客上找到有用的信息:

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