views:

957

answers:

4

Hi Folks,

I have a static object defined in my logging class, along the lines of:

   class myLoggingClass {
     static java.util.Properties properties;
     ...
     ...
   }

According to my reference book, this means that the properties object is shared by all instances of my class.

I find this definition insufficient. I'm writing a class that is being invoked more than once in each application on our project.

Further, our project uses several web services running in the same tomcat container. Each web service may have multiple threads.

The Java Virtual Machine running on the host may also run one or more web service client applications, which run external to tomcat.

So by this definition, I may have tomcat running multiple web services with threads, each having several objects, which may contain an instance of my class.

There may also be one or two web clients running outside of tomcat, but within the same JVM. Would all of these instances of my class share the same properties object? That would make it JVM-wide.

If the static object is not JVM-wide, does anyone know at what level each one would exist? One per tomcat container? One per web service, and one per standalone web service client application?

The reason: When I update my properties, I'm getting a java.lang.ConcurrentUpdateException from java.util.Properties.

I'm using a static boolean variable to "lock" the properties object when my class updates it, but this is not keeping the exception from occurring.

This leads me to believe that the static object used in my class may not be at the same scoping level as the one used in java.util.Properties... But that's just a guess.

Thanks for any help.

+4  A: 

You may find that the scope of such a static variable is limited to one per ClassLoader that has loaded your class. I'm not sure how Tomcat arranges its ClassLoaders, so it's hard to say what the extent of the scope will be in that environment.

Greg Hewgill
+7  A: 

Statics aren't "shared by all instances of a class" - they're unrelated to instances; they belong to the type itself. In particular, static variables are perfectly usable without any instances being created.

That gives a clue as to the scope of statics: they're scoped by the Class object representing the containing class, which is in turn scoped by the ClassLoader that loaded it.

Depending on where the library is placed, the static variable may be JVM-wide or web-application wide - or possibly something in between, if Tomcat supports multiple hosting (I can't remember offhand).

Look at the Tomcat documentation for how the libraries are laid out and how they relate to class loaders. For example, here's the Tomcat 6.0 ClassLoader how-to guide, and the equivalent for 5.5.

How does your Boolean "lock" work? You should really use a proper lock (synchronized) to make sure that every use of the properties object (both read and write, including locking for the whole period during which you iterate through it) is appropriately locked.

Instead of changing the "live" Properties object, have you considered treating that as immutable - so when you want to update the properties, you take a copy, change that, and then make the copy the "live" version? You'd still need to prevent two different threads from making changes at the same time (or you'd lose some) but it's likely to make the reading side a lot easier and more efficient.

Jon Skeet
A: 

Could it be a classloader problem where the jar that contains your class is duplicated in each WEB-INF/lib of your different applications? If so, I would try to add this jar to Tomcat libs and not to the application.

Gaël Marziou
+2  A: 

The likely cause of your ConcurrentModificationException is that you are iterating thru the values/entries of the Properties object in one thread while another modifies it at the same time. You cannot do this.

Can you elaborate on the locking mechanism that you mention here:

I'm using a static boolean variable to "lock" the properties object when my class updates it, but this is not keeping the exception from occurring.

?

Because it doesn't sound as if you are using the built-in locking and synchronization methods in Java.

Something like this should prevent threads from reading the Properties object while another thread updates it:

static Object lockObject = new Object();

...

synchronized(lockObject) {
     // access the Properties object
}

Note that you will need to do this every time you access the Properties object, either to read it or modify it.

Also I would never recommend static objects to share data among all instances or static lockObjects - global data is evil - but it sounds as if you need this for some reason.

matt b
just wanna add a note here to say that I think Jon Skeet's description of how static variables actually work is spot-on, and I would consider this the true answer to the question.
matt b