84

Regarding my previous Question, Why do == comparisons with Integer.valueOf(String) give different results for 127 and 128? , we know that Integer class has a cache which stores values between -128 and 127.

Just wondering, why between -128 and 127?

Integer.valueOf() documentation stated that it "caching frequently requested values" . But does values between -128 and 127 are frequently requested for real? I thought frequently requested values are very subjective.
Is there any possible reason behind this?

From the documentation also stated: "..and may cache other values outside of this range."
How is this can be achieved?

Community
  • 1
  • 1
DnR
  • 3,487
  • 3
  • 23
  • 31
  • 8
    Re the documentation: Oracle are just covering their butts in case they decide to change the behaviour later. For example, they may decide that Java 9 will cache from -1024 to 1023. The message is, don't rely on the cache containing, or not containing, any specific integer. – Dawood ibn Kareem Jan 03 '14 at 05:18
  • 7
    I assume you loop a lot more often from 0 to X than from 13476 to Y. They must have decided that negative values should also be included and -128 -> 127 makes sense for a signed byte. – Jeroen Vannevel Jan 03 '14 at 05:21
  • 2
    Isn't looping almost always done w/ primitive ints -- not boxed Integers? Caching doesn't apply. – bradvido Jan 03 '14 at 21:45
  • 2
    The cache is purely a performance thing. So long as it's not creating a performance problem for you you should not care what range is cached. (It would be the height of folly to build into your code a dependency on Integer caching.) – Hot Licks Jan 06 '14 at 03:50
  • Although the Oracle implementation of the JVM is probably the most predominant, it's is not the only implementation of the JVM. To my knowledge, this behavior isn't part of any specification. It may make sense for other implementations to cache a smaller or larger range of values. The Android documentation is even [more vague](http://developer.android.com/reference/java/lang/Integer.html#valueOf(int)) "...since it maintains a cache of instances which may result in better performance." As @DavidWallace mentioned, it's best not to count on the cache containing specific values – John R Jan 08 '14 at 03:41
  • Frequently used values is subjective, but honestly, how often do you use the integers `..., -1, 0, 1, ...`, etc., compared to `..., 53522, 53523, 535242, ...`? – Keeler Jan 08 '14 at 20:37
  • 3
    @JohnR it's in the Java Language spec, see assylias answer below. – Zac Thompson Jan 09 '14 at 22:47

5 Answers5

112

Just wondering, why between -128 and 127?

A larger range of integers may be cached, but at least those between -128 and 127 must be cached because it is mandated by the Java Language Specification (emphasis mine):

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.

The rationale for this requirement is explained in the same paragraph:

Ideally, boxing a given primitive value p, would always yield an identical reference. In practice, this may not be feasible using existing implementation techniques. The rules above are a pragmatic compromise. The final clause above requires that certain common values always be boxed into indistinguishable objects. [...]

This ensures that in most common cases, the behavior will be the desired one, without imposing an undue performance penalty, especially on small devices. Less memory-limited implementations might, for example, cache all char and short values, as well as int and long values in the range of -32K to +32K.


How can I cache other values outside of this range.?

You can use the -XX:AutoBoxCacheMax JVM option, which is not really documented in the list of available Hotspot JVM Options. However it is mentioned in the comments inside the Integer class around line 590:

The size of the cache may be controlled by the -XX:AutoBoxCacheMax=<size> option.

Note that this is implementation specific and may or may not be available on other JVMs.

Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
  • 3
    This is the complete and best answer - the question confuses the -128 to 127 range with the "frequently requested values", when in fact they are for different reasons. -128 to 127 are cached for boxing. "frequently requested values" are cached for performance. – Zac Thompson Jan 09 '14 at 22:51
  • @ZacThompson, thanks for pointing this out. My previous comment was not correct. The key phrase from the spec is "an int ... 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." So if I understand correctly, the spec mandates that Integer.valueOf(X) == Integer.valueOf(X) where -128 <= X <= 127. – John R Jan 10 '14 at 14:59
  • This is the only answer to the "why" part of the question that offers something other than "it's the default". However, this answer is not complete because it doesn't address the "how" part of the question. Referencing the responses by others on XX:AutoBoxCacheMax and adding information on how to control the caching behavior on other implementations of the JVM (or indicating which JVM implementations have options to control this behavior) would make this a complete answer. – John R Jan 10 '14 at 15:21
  • "In practice, this may not be feasible using existing implementation techniques." I can't get this line. Can you please explain it? – niiraj874u May 15 '14 at 08:46
  • 2
    @niiraj874u The current implementation uses a cache which resides in memory - each "canonical" integer is held in that cache. So caching all integers would mean you may have to hold up to 2^32 integers (= 15+ GB) in memory, which is unreasonable, even on a modern desktop computer. – assylias May 15 '14 at 09:32
  • @assylias, Thanks for your help.. but in general routine project, How caching of this small range is useful? Can you tell me a real time example. I am bit agree with keshlam's answer in this post which says caching is useful for 'many algorithms which use small integers in their calculations' What do you think ? – niiraj874u May 15 '14 at 09:42
23

-128 to 127 is the default size. But javadoc also says that the size of the Integer cache may be controlled by the -XX:AutoBoxCacheMax=<size> option. Note that it sets only high value, low value is always -128. This feature was introduced in 1.6.

As for why -128 to 127 - this is byte value range and it is natural to use it for a very small cache.

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
6

The reason for caching small integers, if that's what you're asking, is that many algorithms use small integers in their calculations, so avoiding the object-creation overhead for these values tends to be worthwhile.

The question then becomes which Integers to cache. Again, speaking in general, the frequency with which constant values are used tends to decrease as the absolute value of the constant increases -- everyone spends a lot of time using the values 1 or 2 or 10, relatively few few use the value 109 very intensively; fewer will have performance depend on how quickly one can obtain an Integer for 722.. Java chose to allocate 256 slots spanning the range of a signed byte value. This decision may have been informed by analyzing programs in existence at the time, but is just as likely to have been a purely arbitrary one. It's a reasonable amount of space to invest, it can be accessed rapidly (mask to find out if the value's in the cache's range, then a quick table lookup to access the cache), and it will definitely cover the most common cases.

In other words, I think the answer to your question is "it isn't as subjective as you thought, but the exact bounds are largely a rule-of-thumb decision ... and experiemental evidence has been that it was good enough."

keshlam
  • 7,931
  • 2
  • 19
  • 33
3

Max high integer value that can be cached can be configured through system property i.e java.lang.Integer.IntegerCache.high(-XX:AutoBoxCacheMax) . The cache is implemented using an array.

    private static class IntegerCache {
    static final int high;
    static final Integer cache[];

    static {
        final int low = -128;

        // high value may be configured by property
        int h = 127;
        if (integerCacheHighPropValue != null) {
            // Use Long.decode here to avoid invoking methods that
            // require Integer's autoboxing cache to be initialized
            int i = Long.decode(integerCacheHighPropValue).intValue();
            i = Math.max(i, 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(i, Integer.MAX_VALUE - -low);
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
    }

    private IntegerCache() {}
}
user987339
  • 10,519
  • 8
  • 40
  • 45
0

When you encounter with Integer class and always boxed within the range -128 to 127 it's always better to convert the Integer object into int value as below.

<Your Integer Object>.intValue()
Teja
  • 13,214
  • 36
  • 93
  • 155