Why Integer class caching values in the range -128 to 127?
Asked Answered
F

5

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?

Fullmer answered 3/1, 2014 at 5:16 Comment(7)
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.Pilchard
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.Metonym
Isn't looping almost always done w/ primitive ints -- not boxed Integers? Caching doesn't apply.Hekate
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.)Wingding
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 "...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 valuesDibble
Frequently used values is subjective, but honestly, how often do you use the integers ..., -1, 0, 1, ..., etc., compared to ..., 53522, 53523, 535242, ...?Celeriac
@JohnR it's in the Java Language spec, see assylias answer below.Lopsided
C
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.

Cymric answered 6/1, 2014 at 10:52 Comment(6)
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.Lopsided
@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.Dibble
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.Dibble
"In practice, this may not be feasible using existing implementation techniques." I can't get this line. Can you please explain it?Solorzano
@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.Cymric
@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 ?Solorzano
R
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.

Risible answered 3/1, 2014 at 5:20 Comment(8)
how we can implement the -XX:AutoBoxCacheMax=<size>?Fullmer
run java -XX:AutoBoxCacheMax=256 ... and you will see that Integer.valueOf(256) == Integer.valueOf(256)Risible
by running java -XX:AutoBoxCacheMax=256 in console, I got Error:could not create the Java Virtual MachineFullmer
try java -version it should be 1.6 or higher, my 1.7 works OKRisible
Yes. mine is 1.7.0_25Fullmer
java -XX:AutoBoxCacheMax=256 X. X is my test System.out.println(Integer.valueOf(256) == Integer.valueOf(256)); and it prints trueRisible
I've read somewhere else and it says that -XX:AutoBoxCacheMax only works on 64-bit?Fullmer
Right, this is why javadoc says ..may be controlled... my Java is 64 bitsRisible
D
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."

Dacca answered 13/1, 2014 at 1:50 Comment(0)
S
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() {}
}
Sulphonate answered 3/1, 2014 at 5:30 Comment(0)
S
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()
Stoffel answered 11/3, 2018 at 4:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.