Scope of Static Class Variables in Java

Scott C. picture Scott C. · Sep 9, 2009 · Viewed 7.4k times · Source

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.

Answer

Jon Skeet picture Jon Skeet · Sep 9, 2009

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.