I'm encountering what appears to be a memory leak in the BrokerService.
The symptom is that the BrokerService's memory usage increases with each
message that is sent to a topic, as though each message is being stored
permanently in memory. 

 

I've included an example which demonstrates the issue. If you run the
included BrokerMemoryLeak.java, you should see the following output:

 

Memory Usage:     0     Memory Percent:   0     Send count: 0     

Memory Usage:     16016576    Memory Percent:   23    Send count: 16    

Memory Usage:     38039368    Memory Percent:   56    Send count: 38    

Memory Usage:     61063196    Memory Percent:   90    Send count: 61    

Memory Usage:     68070448    Memory Percent:   101   Send count: 68    

Memory Usage:     68070448    Memory Percent:   101   Send count: 68    

Memory Usage:     68070448    Memory Percent:   101   Send count: 68

 

BrokerService's memory usage climbs steadily until the memory percent
hits 100. Then, messages stop being sent. There are several ways to make
the bug stop happening:

  * Switch from using a Topic to a Queue

  * Switch the Broker address to 'vm://foo', so it's not using TCP

  * Set the third argument in the 'createConsumer' call to false. (the
noLocal argument)

  * Don't register the MessageListener

 

I've witnessed this behavior both with ActiveMQ 5.1.0 and the
5.2-SNAPSHOT version available as of August 4, 2008. I'm using Spring
2.5.4. Since two-way traffic isn't an issue for this application, I can
fix the issue by setting 'noLocal' to false. However, I wasn't sure
whether I should submit a JIRA tracker for this, or whether I'm doing
something wrong.

 

Thanks,

 

- Aaron Pieper

 

--------------------------------

 

import java.util.HashMap;

import java.util.Timer;

import java.util.TimerTask;

 

import javax.jms.Connection;

import javax.jms.Message;

import javax.jms.MessageConsumer;

import javax.jms.MessageListener;

import javax.jms.Session;

import javax.jms.Topic;

 

import org.apache.activemq.ActiveMQConnectionFactory;

import org.apache.activemq.ActiveMQSession;

import org.apache.activemq.broker.BrokerService;

import org.apache.activemq.usage.MemoryUsage;

import org.springframework.jms.core.JmsTemplate;

 

public class BrokerMemoryLeak {

      private int                   sendCount;

      private BrokerService   broker      = new BrokerService();

 

      public static void main(String[] args) throws Exception {

            new BrokerMemoryLeak().run();

      }

 

      private void run() throws Exception {

            broker.addConnector("tcp://localhost:8192");

            broker.setPersistent(false);

            broker.start();

 

            ActiveMQConnectionFactory connectionFactory = (new
ActiveMQConnectionFactory("tcp://localhost:8192"));

            Connection connection =
connectionFactory.createConnection();

            connection.start();

 

            ActiveMQSession session = (ActiveMQSession)
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

            Topic topic = session.createTopic("foo");

            MessageConsumer messageConsumer =
session.createConsumer(topic, null, true);

 

            messageConsumer.setMessageListener(new MessageListener() {

                  public void onMessage(Message message) {}

            });

 

            TimerTask statusTask = new TimerTask() {

                  @Override

                  public void run() {

                        StringBuffer buf = new StringBuffer();

                        MemoryUsage memoryUsage =
broker.getSystemUsage().getMemoryUsage();

                        buf.append("Memory
Usage:\t").append(memoryUsage.getUsage()).append("\t");

                        buf.append("Memory
Percent:\t").append(memoryUsage.getPercentUsage()).append("\t");

                        buf.append("Send
count:\t").append(sendCount).append("\t");

                        System.out.println(buf);

                  }

            };

 

            new Timer().schedule(statusTask, 0, 1000);

 

            JmsTemplate template = new JmsTemplate();

            template.setConnectionFactory(connectionFactory);

            template.afterPropertiesSet();

 

            while (true) {

                  HashMap<String, Object> map = new HashMap<String,
Object>();

                  map.put("1", new byte[1000000]);

                  template.convertAndSend(topic, map);

                  sendCount++;

                  Thread.sleep(1);

            }

      }

}

Reply via email to