activemq-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bwtaylor <bryan_w_tay...@yahoo.com>
Subject Re: VM transport not using pass-by-reference
Date Thu, 05 Jun 2008 05:34:24 GMT

I traced through some code. It looks like ActiveMQSession.send() does honor
copyMessageOnSend as noted. But this only explains why you see 2001, not
2002 messages. Message consumption on a topic happens in a two step process: 
 1) During dispatch, a MessageDispatch object is enqueued to consumer's
unconsumedMessage MessageDispatchChannel, then 
 2) During receive, the MessageDispatch is dequeued from unconsumedMessage

The message is dispatched via a call to
ActiveMQMessageConsumer.dispatch(MessageDispatch md). If the consumer has a
MessageListener, a copy of the message is sent to it after calls to
createActiveMQMessage(md) and listener.onMessage(message). Then the original
is enqueued to unconsumedMessage. I don't think you actually have such a
listener, so there's a 3rd copy out there that you are missing out on :-)
The copy happens on the first line of createActiveMQMessage:

    private ActiveMQMessage createActiveMQMessage(final MessageDispatch md)
throws JMSException {
        ActiveMQMessage m = (ActiveMQMessage)md.getMessage().copy();
        [... stuff omitted]
        return m;
    }

The dispatch call happens after a long sequence of dispatch calls that go
all the way back to the ActiveMQConnection object. It's onCommand() method
uses a visitor pattern and the CommandVisitorAdapter it uses has this
code...

                    public Response processMessageDispatch(MessageDispatch
md) throws Exception {
                        ActiveMQDispatcher dispatcher =
dispatchers.get(md.getConsumerId());
                        if (dispatcher != null) {
                            // Copy in case a embedded broker is dispatching
via
                            // vm://
                            // md.getMessage() == null to signal end of
queue
                            // browse.
                            Message msg = md.getMessage();
                            if (msg != null) {
                                msg = msg.copy();
                                msg.setReadOnlyBody(true);
                                msg.setReadOnlyProperties(true);
                               
msg.setRedeliveryCounter(md.getRedeliveryCounter());
                                msg.setConnection(ActiveMQConnection.this);
                                md.setMessage(msg);
                            }
                            dispatcher.dispatch(md);
                        }
                        return null;
                    }

According to the comment, this copy is a feature of vm:// transport not a
bug :-)

The other copy is easier to find. When the message is consumed we instead
get a call to ActiveMQMessageConsumer.receive(), which dequeues a
MessageDispatch md from the MessageDispatchChannel unconsumedMessages then
and calls createActiveMQMessage(md), which as we saw above makes a copy.

So 1 copy on dispatch, 1 copy on receive, and a 3rd copy onMessage() if the
consumer has a listener. I have no insight into the motivations here, I just
eyeballed the code and described the relevant parts.

Some good news: message.copy() is a shallow copy: the content (and
everything else) within the message is copied by reference. See
org.apache.activemq.command.Message.copy(Message copy) .
-- 
View this message in context: http://www.nabble.com/VM-transport-not-using-pass-by-reference-tp17442075s2354p17662490.html
Sent from the ActiveMQ - User mailing list archive at Nabble.com.


Mime
View raw message