Can or is the Object held within a JMS ObjectMessage the same instance as when published?
I think this is a stupid question, but I can't quite find the answer I'm looking for in the JMS getting started guide, or indeed elsewhere on the web. This jGuru post suggests that thread safety in the following scenario is up to the application designer.
Scenario
Consider an Object
as an attribute of HttpSession
. This object is of type ProductQuote
.
In a Java Servlet, I take some input from the request and set them to fields in a new instance of ProductQuote
and then use another class of mine to push the same ProductQuote
instance on to a JMS Queue.
On a separate thread, this object is popped from the queue via the container, and passed to my message driven bean ("MDB") that implements MessageListener
via the onMessage(Message message)
method. This particular implementation of the MessageListener
interface will mutate a field in the instance and then discard the message, executing开发者_如何学JAVA cleanly.
Question
Is it possible that the instance of ProductQuote
pushed to the queue in the Servlet the exact same instance that is consumed by the MDB in another thread?
I am assuming the reverse is also possible (if not always; I'm trying to fill a gap in my knowledge): that an instance pushed to a queue/topic is not the same instance as that passed to consumers.
Edit For additional clarification, I am pondering thread safety in the given scenario, where an object in the session could be modified at the same time an MDB is modifying/reading it.
Forgive the stupid question.
I think the answer is - yes, it is possible... (although unlikely) Looking at the JMS specification there appear to be no guarantees around this so it may depend on your chosen JMS provider. Just because the specification says that the Object must implement Serializable does not mean it will be serialized. I would however add that I'd be surprised if it was the same object as JMS is often used to perform messaging between applications and therefore the object must have been serialized.
The answer is defined in the JMS specification and I quote:
Note that the setObject method of ObjectMessage places a copy of the input object in a message
Given that any JMS provider -- in my case BEA Weblogic -- would have to adhere to this, I am confident the thread-safety concern in my original message is unfounded: objects that are in ObjectMessage
instances are copied and therefore the threat of concurrent modification does not exist.
Edit
I should have read the Javadoc too:
public void setObject(Serializable object)
throws JMSException
Sets the serializable object containing this message's data. It is important to note that an ObjectMessage contains a snapshot of the object at the time setObject() is called; subsequent modifications of the object will have no effect on the ObjectMessage body.
Firstly, distinct objects may have the same hash code.
Secondly, I would bet that what is 'inside' the JmsObjectMessage is a serialized version of an object instance, and I imagine that it gets a new Object id when it is deserialized, and the new object instance should produce the same hash code as the object that was originally serialized.
In all likelihood, you will not get back the same object. It may have the same logical identity as the one that was sent, but making changes on it will most likely not result in the original object reflecting that change.
However, it is tough to be completely certain about that without knowing more about the specific object. For example, if the object was a serializable wrapper around another object, and any invocations against the wrapper automatically refreshed the wrapper's reference to the target object, then to all extents and purposes, you have the identical object on either side of the JMS message.
Also, if you examine the JavaDoc for java.io.Serializable, you'll see that there are number of optional methods you can define in a serializable implementation that will be invoked during the serialization/deserialization process.
private void writeObject(java.io.ObjectOutputStream out) throws IOException
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
These methods implemented in the right (or wrong) way could reinforce or belie any of the answers supplied to your question.
精彩评论