Java – Internal Caching in Wrapper Classes

1. Object Creation is Expensive

We know to create objects in java using the new keyword. A new instance created in Java allocates the memory in the heap, so creating new objects is considered an expensive operation.

To avoid this expensive object creation process, many of the frameworks have been evolved during the time, which does specifically resource pooling in different ways.

For example, persistence frameworks use connection pools. Java has String pool concept. Also we have prototype pattern for this purpose. Having ready-made objects has its own benefit and should be promoted as well.

2. Wrapper Classes implement Object Pooling

Wrapper classes are the most used classes in a Java application, similar to String class. Fortunately, similar to String class, wrapper classes are immutable in Java. So, like string pool, we can also have their pool as well.

Well, it’s already there. JDK-provided wrapper classes implement instance pooling. Each wrapper class stores a list of commonly used instances of its own type in form of cache and whenever required, we can use them in our code.

This object pooling helps in saving lots of byes in your program runtime.

2.1. Integer Cache Demonstration

In Integer class, there is an inner class IntegerCache. It is static inner class and will only be initialized when used the first time.

So on the first time, due to cache creation, time might be a little longer and after that, it will not take more time. But, the actual benefit is memory reuse.

private static class IntegerCache
{
    private IntegerCache(){}
    static final Integer cache[] = new Integer[-(-128) + 127 + 1];
    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Integer(i - 128);
    }
}

When we create a new Integer instance with given syntaxes, an already created Integer instance is returned and reference is stored in i.

Integer i = 10; //OR
Integer i = Integer.valueOf(10);
  • Please note that if we use new Integer(10) then a new instance of Integer class will be created and caching will not be used. Using new keyword always creates a new object in the heap.
  • Caching is only available when you use Integer.valueOf() OR directly primitive assignment (which ultimately uses valueOf() function).

This is valueOf() method implementation. See how it returns an already cached instance.

public static Integer valueOf(int i)
{
    final int offset = 128;
    if (i >= -128 && i <= 127) // must cache
        return IntegerCache.cache[i + offset];
    }
    return new Integer(i);
}

2.2. Demo

Let’s see an example in working:

public class IntegerCacheDemo {
 
    public static void main(String[] args) {
 
        Integer a1 = 100;
        Integer a2 = 100;
        Integer a3 = new Integer(100);
 
        System.out.println(a1 == a2);    //true
        System.out.println(a1 == a3);    //false
    }
}
  • The first print statement will print true; means both variables are referring to the same instance.
  • Second print statement prints false, because the new Integer(..) created a new fresh instance in the memory.

So, if we want to make use of the internal cache, always use primitive assignment to reference variable or use valueOf() method.

3. Modifying Internal Cache Size

If we want to store a bigger number of instances, we can use runtime parameter as below:

-Djava.lang.Integer.IntegerCache.high=<size>

Or we can use the JVM setting:

-XX:AutoBoxCacheMax=<size>

The size of 2000 will cause the cache to store instances from -127 to 2000. Remember, there is no such property for a lower limit as of now. Maybe in the future, it might be added as well.

4. Other Wrapper Classes

In above discussion, I have talked about cache in Integer class, but if fact all wrapper classes provide instance pooling. Lets see them quickly:

  1. java.lang.Boolean store two inbuilt instances TRUE and FALSE, and return their reference if new keyword is not used.
  2. java.lang.Character has a cache for chars between unicodes 0 and 127 (ascii-7 / us-ascii).
  3. java.lang.Long has a cache for long between -128 to +127.

Happy Learning !!

Comments

Subscribe
Notify of
guest
9 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode