0

我有一个 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。

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 回答