:  other :  cfr :  boxing caches

You probably know that there is a predefined cache of boxed integers, such that Integer.valueOf(1) will always return the same pointer.

The java language spec (jls-5.1.7) describes this here.

The salient line is: If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.

Some discussion about the original design can be found at Joseph Darcy's blog entry on IntegerCache.

Autoboxing uses valueOf

As I described here, autoboxing uses valueOf. This means that

  Integer i = 3;
  Integer j = new Integer(3);

is actually compiled to

  Integer i = Integer.valueOf(3);
  Integer j = new Integer(3);

i.e the latter WON'T use the integer cache...

How is the cache implemented

This is described in detail in the blog entry linked above, and of course the source is publically available, but it's a good test of CFR, so here's Integer.valueOf()

public static Integer valueOf(int v0){
    if (!((Integer.$assertionsDisabled) || (Integer$IntegerCache.high >= 127))) {
        throw new AssertionError();
    if ((v0 >= -128) && (v0 <= Integer$IntegerCache.high)) {
        return Integer$IntegerCache.cache[(v0 + 128)];
    return new Integer(v0);

Ok, so what about Integer.IntegerCache?

class Integer$IntegerCache
static final int low = -128;
static final int high;
static final Integer[] cache;

static void <clinit>(){
    int v0 = 127;
    String v1 = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
    if (v1 != null) {
        int v2 = Integer.parseInt(v1);
        v2 = Math.max(v2, 127);
        v0 = Math.min(v2, 2147483519); // LEE - Integer.MAX_VALUE - 128!
    Integer$IntegerCache.high = v0;
    Integer$IntegerCache.cache = new Integer[(Integer$IntegerCache.high - -128 + 1)];
    int v2 = -128;
    for (int v3 = 0;v3 < Integer$IntegerCache.cache.length; ++v3) {
        Integer$IntegerCache.cache[v3] = new Integer(v2++);

... that's interesting, I didn't know that one! .... we can extend the range of the integer cache!

Last updated 03/2013