Search code examples
javalazy-loading

Less verbose way to do lazy loading


I am refactoring a class called ConfigNode that stores 50 "properties". Each property is an object of its own. All properties are optional, and most of the time, many of them are not set.

Currently, the class is written so that when it is instantiated, all 50 properties are instantiated as well. When you create a million Config objects, Java tells me I'm using 2.5 gigs of memory. When I comment out the property instantiation, Java says I'm using 300 MB.

The benchmark code I'm using is

Runtime.getRuntime().gc();
// do my stuff
Runtime.getRuntime().gc();
long memory = Runtime.getRuntime().totalMemory();
System.out.println("Memory used: " + memory / 1000000 + " MB");

So I'm thinking of rewriting the class to lazy load a property when it's accessed, but having to write something like

// This is probably not thread safe, so it could be even more verbose
public NodeProperty propOne() {
   if (propOne == null) {
      propOne = new NodeProperty( ... )
   }
   return propOne
}

And then do it for all of the properties seems kind of verbose. Is there anything in Java that can help me reduce the amount of code I have to write (and consequently, maintain)?

Here is how the NodeConfig looks like

public class NodeConfig {

    public NodeProperty pVersion = new NodeProperty( "Spec Version", Status.REQUIRED, Visibility.HIDDEN);
    public NodeProperty pTwoWay = new NodeProperty( "Two way", Status.OPTIONAL, Visibility.VISIBLE );
    public NodeProperty pBinary = new NodeProperty( "Binary mode", Status.OPTIONAL, Visibility.HIDDEN);

    // more properties

    public NodeConfig() {
        // 
    }
}

Solution

  • Approach 1
    Here's another approach you could use given the NodeConfig code: public class NodeConfig {

        public NodeProperty pTwoWay;
        public NodeProperty pBinary;
    
        // more properties
    
        public NodeConfig() {
            // 
        }
    
        public NodeProperty getProperty(NodePropertyEnum nodeProp) {
            switch(nodeProp) {
                case TWO_WAY: 
                    if (pTwoWay != null) {return pTwoWay;}
                    pTwoWay = new NodeProperty( "Two way", Status.OPTIONAL, Visibility.VISIBLE ); 
                case BINARY_MODE: 
                    if (pBinary != null) {return pBinary;}
                    pBinary = new NodeProperty( "Binary mode", Status.OPTIONAL, Visibility.VISIBLE); 
                // other cases
                default: 
                    throw new IllegalArgumentException();
            }
        }
    }
    

    Approach 2
    Looks like a case for Singleton design pattern. Rather than checking for propOne instance to be null, it will be better if you make all Property classes singleton. Something like:

    public class NodeProperty {
    
        private static volatile NodeProperty instance = null;
    
        private NodeProperty() {
            // instantiatin logic
        }
    
        public NodeProperty getInstance() {
            if(instance == null) {
                synchronized(NodeProperty.class) {
                    if(instance==null) {
                        instance = new NodeProperty();
                    }
                } 
            }
        }
    
    }