Understanding the interplay between utility classes and static initialization

Java is an OO language. Much of the functionality of an application is encapsulated into cohesive classes that can be instantiated and acted upon. Nevertheless once in a while you end up with some functions that are applicable to more than one class. These functions don't really belong any particular class but to a sub system or a package. Although one can express this grouping as a class by itself represented by interfaces, it is just simpler to collect them as static functions in a class, when one doesn't need the sophistication of service centric approach for these methods.

For example I have a class called ServletUtils.


public class ServletUtils
{
   static public void 
   writeOutAsJavaScript(PrintWriter out, StringBuffer javaScript);
   
   static public String 
   convertToHtmlLines(String inString);
   
   static public Map 
   parseQueryString(String httpQueryString);
   
   static public Map 
   getParameters(HttpServletRequest request);
   
   .. so on and so forth
}   

I have a similar class for FileUtils


public class FileUtils
{
   static public void 
   runFileProcessorWith(String filename,
               IFileProcessorListener callBackProcessor);
   throws IOException;
      
   static public String 
   translateRelativeFilename(String filename);
   
   static public String
   copy(String fromFile, String toFile) 
   throws IOException;               
   
   static public String
   getBaseName(String filename);
   
   static public String
   getAbsolutePath(String filename);
   
   .. so on and so forth            
}

One characteristic of static functions is that they are stateless. But for efficiency they may depend on some static variables. When this happens you need to know the class initialization rules laid out by the language. Although these rules are fairly intuitive rules it is beneficial to know them in some depth, as static initialization result in side affects.

This article is about minimizing these side affects.

With that in mind let me review the basics of static initialization rules. For a compplete treatment of the rules refer to the java language specification links at the end of the article.

Simplified rules of static initialization

  1. A class is initialized before any of its members are accessed. This includes class variables and static functions.
  2. Before a class is initialized its superclass is initialzed first
  3. You can use static blocks to initialize static variables
  4. Static variables and static blocks are executed in the order they appear in source code(so called textual order)
  5. A class is initialized before any of its instances can exist

Rules of static blocks

  1. Cannot return
  2. Can throw runtime exceptions
  3. Cannot throw checked exceptions
  4. Cannot call this or super

Static initialization surprise


public class super
{
   public static int i=10;
   static 
   {
      System.out.println("Super called");
   }
}

public class child extends super 
{
   static { System.out.println("Child initialized");}
}

public class test
{
   public f1()
   {
      int j = child.i;
   }
}

This test code will not initialize the child although the variable is invoked through its namespace, because the variable belonged to the super class. So you will only see "Super called" printed and not "Child initialized".

The shock affect of static access

Static access happens when you access a static variable or invoke a static method, or instantiate one of its type. This will automatically trigger a whole lot of things. First off the class they are part of is initialized if it is not already initialized. This implies all of the static fields will be initialized. If this initialization involves any newing of classes, then a whole lot of constructors are called. This is followed by the execution of numerous static blocks that are there for that class. In fact the side affects are further compounded when the class in case is inheriting other classes as those classes get initialized first.

Back to the utility class again

As stated earlier a class with a set of related static methods can be called a utility class. Let me consider another example this time.


public class sc
{
   public static void sf1();
   public static void sf2();
   public static void sf3();
}

This class defines three static methods.

Optimizing the static function: sf2()

Assume that sf2() is called all the time and requires optimization


public static void sf2()
{
   SomeResource r = new SomeResource();
   r.primeTheResource();
   doSomething(r,"otherstuff");
}

If "r" is not changing I would like to cache it and use a static block to initialize it


public class sc
{
   private static SomeResource r = null;
   static
   {
      SomeResource r = new SomeResource();
      r.primeTheResource();
   }
   public static void sf1();
   public static void sf2() 
         { doSomething(r, "otherstuff");
   public static void sf3();
}

Suppose there is a rule that "primeTheResource()" cannot be called unless the system is initialized. This means there is a point in the application initialization process before which "r.primeTheResource()" is invalid. The author of "sf2()" is quite confident that "sf2()" is always called after the application initialization. But the static class "sc" is designed to be a utility class. So the application initialization process sees that there is a very useful function called "sf1" and decides to use it as part of the initialization process.

Guess what now. Calling "sf1" as part of initialization has invoked "r.primeTheResource()" which expects the initialization to be complete before being valid.

This happened because I broke the class cohesion rule where it says that a class is not a general collection of methods but a cohesive related module. This is usually correct when I am designing instance classes. But this being a utility class, it is a pain to design 'n' utility classes for 'n' purposes.

Solution: Static Resource Holder Pattern

This can be solved by using a holder class for that one resource and get the dependency out of the utility class "sc". Here is an example


public class sc
{
   public static void sf1();
   public static void sf2() 
      { doSomething(ResourceHolder.r, "otherstuff");
   public static void sf3();
}

See how the static class no longer holds a reference to the static variable "r", instead borrows it from its holder class. Here is the ResourceHolder class that hosts the static variale "r" and initializes it at its first use


public class ResourceHolder
{
   public static SomeResource r = null;
   static
   {
      SomeResource r = new SomeResource();
      r.primeTheResource();
   }
}

Actual example from Aspire

So far I have talked about abstract examples to show the Resource Holder pattern. Let me now give a concrete example taken from the source of Aspire a declarative RAD tool for J2EE and XML. The following method is responsible for embedding a "urlString" with proper parameters so that the expanded string will have the user parameters susbstituted. As an example consider the following parameterized urlString:


/{aspireContext}/display/url=ShowPage1URL&arg1={arg1}&arg2={arg2.encode}

If aspireContext is "akc" and arg1 is "15" and arg2 is "abc xyz" then the expanded string will look like


/akc/display/url=ShowPage1URL&arg1=15&arg2=abc+xyz

Now let me consider the static method that does this


public static String getSubstitutedURL(String urlString, 
                           Map args)
  {
   Map map = new HashMap();

   //Shell dictionary
   IDictionary paramDictionary = new MapDictionary(map);

   //Search context dictionary first
   paramDictionary.addChild(ContextDictionaryHolder.s_contextDictionary);

   //Search url arguments next
   paramDictionary.addChild(new MapDictionary(args));

   //Search configuration last
   paramDictionary.addChild(ConfigDictionary.self);

   //Replace
   return SubstitutorUtils.urlencodeSubstitute(urlString,paramDictionary);
  }

The method uses hierarchical dictionaries to resolve parameter names to their values. Importantly for this discussion it uses a cached dictionary called "context dictionary" which is always the same for a given web context. Instead of maintaining a static variable inside the class it uses a "ContextDictionaryHolder" class to do that. The code for this class follows.


class ContextDictionaryHolder
{
   public static IDictionary s_contextDictionary = null;
   static
   {
      String aspireContext = ServletUtils.getWebApplicationContext();
      if (aspireContext == null) aspireContext = "";
      HashMap m = new HashMap();
      m.put("aspirecontext",aspireContext);
      s_contextDictionary = new MapDictionary(m);
   }//end of function
}//end of class

See how the static variable s_contextDictionary is initialized using a static block and how the side affects are localized to only this class.

References

1. Class initialization process from the Java Language Specification, 2nd edition

2. Static initializer syntax regulations from the Java Language Specification, 2nd edition

3. Static constructors demystified at O'Reilly's ONDotnet.com

4. Author's web logs