java static fields

A great many people starting out with java development have only a vague understanding of the difference between a "public static String", "public String", and the difference between a class and an object. As this was confusing to me at first, I thought I would give a quick overview.

A class defines a template for what data and operations are available when you tell the JVM to create an object.

So, for example:

class BlogPost {
    public BlogPost(String inString) {
       text = inString;
       BlogPost.latest = this;
    }
    public String text = "";
    public static BlogPost latest;
   
}

When you do the following

BlogPost myPost = new BlogPost("Hello");

You're telling the JVM to allocate some memory on the heap to store a reference to a memory location and from now on, when I refer to myPost, it means that memory location. BlogPost is a class, myPost is an Object that is a reference to a memory location that is an instance of the BlogPost Class. When I'm trying to create a new instance of a BlogPost, the JVM searches it's classpath for a compiled Class definition of Type BlogPost with a constructor that takes a single argument which is a String object.

The important detail some people miss at first is that "static" fields and methods work on the Class definition, not on the Object instance. This means that if you create an instance of a BlogPost, and read the "latest" field, you will not get 5 different values, you'll only going to get the reference to the last one. This has implications for thread safety and other situations where multiple objects may read or write the same static field.

Further complicating the issue is that java can have multiple classloaders which means if "BlogPost" is found in different places (or even in different threads potentially) there might actually be multiple instances of the Class definition. This can make for interesting debugging situations where a static field is updated twice, but only one of them is visible from a particular perspective at a given time. As an illustration, suppose the following two snippets of code appear in different parts of a system:

BlogPost myPost1 = new BlogPost("Hello1");
BlogPost myPost2 = new BlogPost("Hello2");

If myPost1 happens first and myPost2 happens second, most people would expect BlogPost.latest to always refer to myPost2. This is not always the case though, in a web container, if myPost1 was created in a different classloader than myPost2, it's quite possible that certain parts of the system will ALWAYS see BlogPost.latest as myPost1 and other parts will ALWAYS see MyPost2, no matter what order these calls were made. Worse yet, it's possible that, if the class was garbage collected, you might see neither, even though most people would never expect that to happen.

Examples of how this might happen are when you deploy a jar file to a web container in it's parent classpath (like xml processing libraries) and also deploy them inside the web application (or in two different web applications in the same container). Depending on how the container handles the situation, you may very well get different results (even from what I described).

For a more complete set of examples and a better explaination, particularly in regard to implementing Singletons in java, see this

Comments

Popular posts from this blog

Push versus pull deployment models

the myth of asynchronous JDBC

MACH TEN Addendum: for companies wanting to use MACH platforms