Extending java Integer cache
Asked Answered
Q

6

4

There's a general advice to use Integer.valueOf(int) instead of new Integer(int) because of caching.

In JDK 5+, you should really use valueOf because Integer now caches Integer objects between -128 and 127 and can hand you back the same exact Integer(0) object every time instead of wasting an object construction on a brand new identical Integer object.

How can extend the range?

Quotha answered 14/10, 2010 at 14:34 Comment(0)
S
14

You can use the java.lang.Integer.IntegerCache.high property to increase the size of this cache.
ex :

java -Djava.lang.Integer.IntegerCache.high=4096 SomeClass.class
Soak answered 14/10, 2010 at 17:3 Comment(0)
E
2

My questions to you are:

1) Why is your code making new Integer objects hurting you? Do you have a profile result to share, to prove that making too many Integers is slowing your down? Object pooling, in general, is a BAD idea. You need a good case to justify it.

2) Why are you doing new Integer(int)? If you just keep it as a primitive int, not only will you avoid "creating a new object". you will not create any object at all. Auto boxing will handle converting it to an Integer if you need it at a later point in time.

*Disclaimer I Don't use EITHER.. I write performance sensitive code, but have never come to a point where I would manually turn a primitive int into an Integer. I just keep as an int whenever possible, and let the JVM autobox if it is needed.

Ebarta answered 14/10, 2010 at 14:39 Comment(1)
Although you don't specifically answer the OP's question, I 100% agree with you here. Pooling such "cheap" Objects is almost certainly a bad idea.Sampan
L
2

Apparently, the -XX:+AggressiveOpts sets the max to 20000. See the answer on How large is the Integer cache?

Legation answered 7/3, 2014 at 22:22 Comment(0)
P
1

Extending the range of the cache may not get you what you are wanting, but if you have a real need to cache a greater range, you can use this code instead of Integer.valueOf(int). You just need to adjust the cache range values to the range you want.

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); 
    }
}

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);
}

The code is from: http://www.owasp.org/index.php/Java_gotchas

Pickering answered 14/10, 2010 at 14:50 Comment(0)
Y
1

This is why the integer cache was added:

[...] to support the object identity semantics of autoboxing for values between -128 and 127 (inclusive), as required by the language specification.

If you profiled your app and you noticed that creating Integer objects is a hotspot, then by all means, copy the integer cache code and write your own with a different range. Otherwise your time would be better spent finding the real hotspots and improving those.

Yukyukaghir answered 3/4, 2011 at 9:40 Comment(0)
P
0

Using java 8+ features of lambdas and the Map interface and you can do it like so. Create an independent cache using a Map that is preserved due to closure. This cache will be accessed during all invocations of get() for each newCache that is created.

  • get(int value) will return the same instance if it is under the limit, otherwise, it returns the new instance.
  • Map.computeIfAbsent() will place the instance in the map if it is not there. The value that is in the map (just added or existing) will be returned;
@FunctionalInterface
interface IntegerCache {

    Integer get(int value);

    static IntegerCache newCache(int limit) {
        // create a closure of the map and return the method
        final Map<Integer, Integer> cache = new HashMap<>();

        return value -> {
            Integer retVal = Integer.valueOf(value);
            if (value < limit) {
                return cache.computeIfAbsent(value, v -> Integer.valueOf(v));
            }
            return retVal;
        };
    }
}
IntegerCache cache = IntegerCache.newCache(1001);
Integer a = cache.get(1000);  // under the limt
Integer b = cache.get(1000);
System.out.println(a == b);
a = cache.get(1002);          // over the limit
b = cache.get(1002);
System.out.println(a == b);

prints

true
false
Postpone answered 6/3, 2023 at 16:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.