I haven't spent a ton of time using the VM transport personally (I exclusively use SSL/TCP) but at this point it is pretty clear to me that this is just a case of the documentation is old and doesn't apply to ActiveMQ 5.x and it's safe to assume the messages are copied.
ActiveMQ has been around for something like 15 years so it is likely that the behavior used to be one way and then changed and that specific piece of documentation was never updated or removed. ActiveMQ version 5.x has been around since 2008 so I don't know that too many people remember older versions like version 4.x and how things used to be (I know I wasn't around that long ago). Ideally all the documentation should be up to date but sometimes things get missed. Besides what I already sent to show the message is being copied on send, I also just did a quick search and it looks like it also gets copied on dispatch to a consumer therefore you are never going to get "pass by reference" behavior which is what you have verified in your own testing. See: https://github.com/apache/activemq/blob/activemq-5.16.1/activemq-client/src/main/java/org/apache/activemq/ActiveMQConnection.java#L1840 . There are certainly lots of unit tests that use the VMTransport but I don't know that there are any specific tests to demonstrate pass by value or reference, I'm guessing there is nothing else than what you already found and testing it yourself is probably the best thing which you have done. The main action point here is that documentation is quite confusing and needs to be fixed up (probably just deleted honestly) as it doesn't appear to be relevant anymore. On Thu, Apr 1, 2021 at 2:48 PM Cunningham <[email protected]> wrote: > > "...that was just referring to the fact that when the message is sent by > VM transport the same reference is used..." > > That answers my question #1. Thanks. > > > > "...changes to the original message after sending would also affect the > message that was already sent since they are the same object still..." > > Thanks. My experiments show that is true only if > ActiveMQObjectMessage.setObject(new Object()) is done in the producer after > the original send. The same change when done in consumers has no effect. In > both cases I set ActiveMQObjectMessage.setReadOnlyBody(false) beforehand, > by the way. > > If you have running code that implements what you're describing, I'd be > grateful if you could share it. Please? TIA. > > > > "...See: .../org/apache/activemq/ActiveMQSession.java#L1955..." > > Forgive me if I sound ungrateful. But I had already seen that. Thanks just > the same though. > > I've also seen the unit test for it [1]. And I've seen where it's used with > objectMessageSerializationDefered [2]. ActiveMQObjectMessage.setObject() > also uses objectMessageSerializationDefered [3]. > > Another test I've seen is one that verifies that an ObjectMessage's body is > serialized over TCP transport but not serialized over VM transport when > objectMessageSerializationDefered is true [4]. > > > > "...a copy of the message is still sent even with the VM transport by > default..." > > That might explain why I haven't had any luck producing pass-by-reference > behavior (as I understand it [5]) in my experiments. > > Starting with this ActiveMQ-supplied example code [6] as a base, I tried > every combination of values for objectMessageSerializationDefered and > copyMessageOnSend I could think of. > > That documentation I linked to in my first post claims "Messages are passed > by reference when objectMessageSerializationDefered is false" and "Messages > are passed by value when objectMessageSerializationDefered is true". I > would love to find a test that either verifies either of those claims or > disproves either of them. > > Until I do though, I will still have these unanswered questions... > > 1. ... > 2. Where can I find existing unit tests that exercise and verify ActiveMQ's > expected pass-by-reference/pass-by-value behavior? > 3. Is that ActiveMQ documentation even relevant for ActiveMQ 5+? Or only > for 3x and 4x? > > ---- > > [1] https://bit.ly/testAMQcopy > [2] https://bit.ly/AMQcopy > [3] https://bit.ly/setObject > [4] https://bit.ly/MsgNotSerTest > [5] https://bit.ly/JavaDudePbV > [6] https://bit.ly/HelloAMQApp > > > ---- > > On Thu, Apr 1, 2021 at 2:39 PM Christopher Shannon < > [email protected]> wrote: > > > I forgot to add that your experiment probably didn't show changes > because I > > believe by default the ActiveMQConnection has the flag > "copyMessageOnSend" > > set to true. So the message would have been copied anyways into a new > > object which means the whole copy by reference wording is even less > > relevant and more wrong since a copy of the message is still sent even > with > > the VM transport by default. > > > > See: > > https://activemq.apache.org/connection-configuration-uri > > > > > https://github.com/apache/activemq/blob/activemq-5.16.1/activemq-client/src/main/java/org/apache/activemq/ActiveMQSession.java#L1955 > > > > On Thu, Apr 1, 2021 at 8:28 AM Christopher Shannon < > > [email protected]> wrote: > > > > > Yes, Java is pass by value but the value is a copy of the reference and > > > not an independent copy of the message (unlike C or C++). The > > documentation > > > wording should be fixed as it is wrong as you pointed out but I assume > > > whoever wrote that was just referring to the fact that when the message > > is > > > sent by VM transport the same reference is used so you need to be > careful > > > as changes to the original message after sending would also affect the > > > message that was already sent since they are the same object still. The > > > messages are just stored in a data structure in the JVM (I think a > > > LinkedBlockingQueue). So this is just (poorly) trying to convey the > fact > > > that the messages are not independent copies of the message like they > > > would be if sent over TCP or another protocol. > > > > > >
