Integer Caching in Java


28 Mar 2019  Sergio Martin Rubio  3 mins read.

Java provides some optimizations for integers, so instances of Integer are cached by the JVM to increase performance.

How it works

Basically, the cache is not built on demand: Integer holds a private static nested IntegerCache class whose objects are all created up front, the first time Integer is initialized. Boxing a value then only has to check the bounds and return the pre-existing instance from that array. The default range is set from -128 to 127, however, it can be tweaked by the -XX:AutoBoxCacheMax= option, so that, during VM startup, java.lang.Integer.IntegerCache.high will contain the new value and saved in the sun.misc.VM class.

Example

As an example, every time we initialize an Integer like Integer num = 127; the compiler will use the auto-boxing and convert this line to Integer num = Integer.valueOf(127);. This static method will return the cached instance if the value is between -128 and 127.

Since Java 9, Integer(int) has been deprecated in favor of valueOf(int) in order to improve performance. The main difference is that the static method valueOf(int) will use cache, whereas the traditional Integer constructor will always get a new instance.

valueOf(int): Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.

valueOf(int) javadoc in Integer class from java.lang library

Therefore, next time you initialize an Integer with the same value, it will not create a new instance, instead it will return the one that has been already created. This can be simulated by running the following main method:

public static void main(String[] args) {
    Integer i1 = 128, i2 = 128;
    Integer i3 = 127, i4 = 127;
    System.out.println(i1 == i2);
    System.out.println(i3 == i4);
}

output:

false
true

Conclusion

Small integer values occur much more often than big values and therefore it makes sense to avoid the overhead of having different objects for every instance (on a 64-bit JVM with compressed oops an Integer instance consumes 16 bytes: a 12-byte header plus the 4-byte int, already aligned), so always avoid the use of the Integer constructor (new Integer(int)), which has been deprecated since Java 9.

Finally, this feature it not exclusive of Integer, other classes like Boolean, Byte, Short, Long and Character are also using cache to improve performance.