JMS threads sharing locally-instantiated objects?

I have implemented a JMS Queue which is answered by a JBoss-managed pool of Message-Driven Beans; the deployment descriptor allows the MDB to run in as many as 15 threads simultaneously, so there are usually multiple instances of onMessage() running at once.

The problem which I'm having is that objects instantiated by onMessage in one thread appear to be allocated to memory shared with the equivalent object in another thread, causing data collision problems which would normally be associated with data race conditions. My onMessage code looks something like this:

publicvoid onMessage(Message inMessage){

XMLComboObject generator;

...

generator =new XMLComboObject();

XMLComboObject is a custom class which contains multiple instances of XMLTag, another class I wrote to represent the structure of an XML tree. Each one of these is a very large object, so any given instance of XMLComboObject consumes a sizeable amount of memory.

XMLTag contains a method called replaceContents(String tagName, String newContents) which deletes the current contents of an XML tag withing the object and replaces them with the new String:

...

replaceContents(String tagName, String newContents){

deleteContents(tagName);

addContents(tagName, newContents);

}

...

All of the sources I've read about Java threads indicate that local variables are inherently thread-safe, as they are allocated on the stack, which is not shared among threads. However, when I try to dump the contents of the XML tag from an XMLComboObject associated with one thread, I frequently (but erratically) find that the values contained within a tag are concatenated with values which should be associated with another thread. So where I should see:

THREAD ONE VALUES

...

<someTag>AAAAA</someTag>

...

THREAD TWO VALUES

...

<someTag>BBBBB</someTag>

...

I often see:

THREAD ONE VALUES

...

<someTag>AAAAABBBBB</someTag>

...

THREAD TWO VALUES

...

<someTag>AAAAABBBBB</someTag>

...

The only thing I can think of which could be happening here is that both threads are running replaceContents simultaneously on the same XMLTag object, and thus encountering a race condition. This shouldnever be the case, however, since the XMLTags in question are subordinate to a local variable within onMessage(), which is (to the best of my understanding) assumed NOT to be shared among threads.

So is there any way that Java could be attempting to re-use local instances of the objects that I'm instantiating, and in the process sharing memory which needs to be local to a given JMS thread? I can't find any documentation for such a behavior, but it's the only possibility which is coming to mind.

Thanks,

Branden Smith

[3146 byte] By [sumitsua] at [2007-10-2 20:15:21]
# 1

The local variables in the onMessage method are never shared. I guess the problem with the code might lie in the implementation of the XMLComboObject. Does it contain any static members? Also, just for your confirmation that the local variables are not shared across threads, you can add the following statement in the onMessage method after creating the XMLComboObject:

System.out.println("XMLComboObject JVM id is: " + generator.toString());

This would display the object id. You will see that each onMessage method will output a different id.

jaikirana at 2007-7-13 22:57:38 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 2

Thanks for the reply. Unfortunately, I don't have any static members in XMLComboObject, so that can't be the cause.

I did add statements to print out the toString() and hashCode() values for the XMLComboObject classes. In cases where the output appears "merged", they are identical:

THREAD ONE

XMLComboObject@1b46c0d

28601357

THREAD TWO

XMLComboObject@1b46c0d

28601357

I don't know how this is happening, but the two references definitely seem to be pointing to the same thing.

Any ideas?

sumitsua at 2007-7-13 22:57:38 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 3

>In

> cases where the output appears "merged", they are

> identical:

>

> THREAD ONE

> XMLComboObject@1b46c0d

> 28601357

>

> THREAD TWO

> XMLComboObject@1b46c0d

> 28601357

That baffles me

jaikirana at 2007-7-13 22:57:38 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 4

Can you just try out the following thing in your on message code:

Just before creating the XMLComboObject(using new()), put the Thread to sleep for random time(not more than 2 seconds maybe). I was trying to figure out if this had something to do with multiple threads trying to create a object simultaneously(ideally, this should NOT be a issue). The reason i mention random time, is because we dont want to end up specifying a constant time in both the threads and again end up with a race condition while creating the object.

Something like:

void onMessage(...) {

Random randomGenerator = new Random();

int randomTimeToSleep = randomGenerator.nextInt(6) * 1000; //convert to milliSec

System.out.println("Sleeping for: " + randomTimeToSleep);

Thread.sleep(randomTimeToSleep);

XMLComboObject generator = new XMLComboObject();

System.out.println("XMLComboObject id is: " + generator.toString());

}

Try and see whether after adding this Sleep, you still see the issue. You might want to play with the maximum time to sleep in the above code.

jaikirana at 2007-7-13 22:57:38 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 5

For the time being, I've eliminated the problem by restricting JBoss to one MDB to handle each JMS queue. Not my preferred solution, but it seems to be adequate for the time being.

Thanks again for the suggestions, though. If no one else can come up with an explanation / remedy for this really weird problem in the next few days, I'll give you the "DukeDollars".

sumitsua at 2007-7-13 22:57:38 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...