How many objects are created by using the Integer wrapper class?

JavaIntegerWrapper

Java Problem Overview


Integer i = 3; 
i = i + 1; 
Integer j = i; 
j = i + j; 

How many objects are created as a result of the statements in the sample code above and why? Is there any IDE in which we can see how many objects are created (maybe in a debug mode)?

Java Solutions


Solution 1 - Java

The answer, surprisingly, is zero.

All the Integers from -128 to +127 are pre-computed by the JVM.

Your code creates references to these existing objects.

Solution 2 - Java

The strictly correct answer is that the number of Integer objects created is indeterminate. It could be between 0 and 3, or 2561 or even more2, depending on

  • the Java platform3,
  • whether this is the first time that this code is executed, and
  • (potentially) whether other code that relies on boxing of int values runs before it4.

The Integer values for -128 to 127 are not strictly required to be precomputed. In fact, JLS 5.1.7 which specified the Boxing conversion says this:

> If the value p being boxed is an integer literal of type int between -128 and 127 inclusive (§3.10.1) ... then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.

Two things to note:

  • The JLS only requires this for >>literals<<.
  • The JLS does not mandate eager caching of the values. Lazy caching also satisfies the JLS's behavioral requirements.

Even the javadoc for Integer.valueof(int) does not specify that the results are cached eagerly.

If we examine the Java SE source code for java.lang.Integer from Java 6 through 8, it is clear that the current Java SE implementation strategy is to precompute the values. However, for various reasons (see above) that is still not enough to allow us to give a definite answer to the "how many objects" question.


1 - It could be 256 if execution of the above code triggers class initialization for Integer in a version of Java where the cache is eagerly initialized during class initialization.

2 - It could be even more, if the cache is larger than the JVM spec requires. The cache size can be increased via a JVM option in some versions of Java.

3 - In addition to the platform's general approach to implementing boxing, a compiler could spot that some or all of the computation could be done at compile time or optimized it away entirely.

4 - Such code could trigger either lazy or eager initialization of the integer cache.

Solution 3 - Java

First of all: The answer you are looking for is 0, as others already mentioned.

But let's go a bit deeper. As Stephen menthioned it depends on the time you execute it. Because the cache is actually lazy initialized.

If you look at the documentation of java.lang.Integer.IntegerCache:

> The cache is initialized on first usage.

This means that if it is the first time you call any Integer you actually create:

  • 256 Integer Objects (or more: see below)
  • 1 Object for the Array to store the Integers
  • Let's ignore the Objects needed for Store the Class (and Methods / Fields). They are anyway stored in the metaspace.

From the second time on you call them, you create 0 Objects.


Things get more funny once you make the numbers a bit higher. E.g. by the following example:

Integer i = 1500; 

Valid options here are: 0, 1 or any number between 1629 to 2147483776 (this time only counting the created Integer-values. Why? The answer is given in the next sentence of Integer-Cache definition:

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

So you actually can vary the size of the cache which is implemented.

Which means you can reach for above line:

  • 1: new Object if your cache is smaller than 1500
  • 0: new Objects if your cache has been initialized before and contains 1500
  • 1629: new (Integer) - Objects if your cache is set to exactly 1500 and has not been initialized yet. Then Integer-values from -128 to 1500 will be created.
  • As in the sentence above you reach any amount of integer Objects here up to: Integer.MAX_VALUE + 129, which is the mentioned: 2147483776.

Keep in mind: This is only guaranteed on Oracle / Open JDK (i checked Version 7 and 8)

As you can see the completely correct answer is not so easy to get. But just saying 0 will make people happy.


PS: using the menthoned parameter can make the following statement true: Integer.valueOf(1500) == 1500

Solution 4 - Java

The compiler unboxes the Integer objects to ints to do arithmetic with them by calling intValue() on them, and it calls Integer.valueOf to box the int results when they are assigned to Integer variables, so your example is equivalent to:

Integer i = Integer.valueOf(3);
i = Integer.valueOf(i.intValue() + 1);
Integer j = i;
j = Integer.valueOf(i.intValue() + j.intValue());

The assignment j = i; is a completely normal object reference assignment which creates no new objects. It does no boxing or unboxing, and doesn't need to as Integer objects are immutable.

The valueOf method is allowed to cache objects and return the same instance each time for a particular number. It is required to cache ints −128 through +127. For your starting number of i = 3, all the numbers are small and guaranteed to be cached, so the number of objects that need to be created is 0. Strictly speaking, valueOf is allowed to cache instances lazily rather than having them all pre-generated, so the example might still create objects the first time, but if the code is run repeatedly during a program the number of objects created each time on average approaches 0.

What if you start with a larger number whose instances will not be cached (e.g., i = 300)? Then each valueOf call must create one new Integer object, and the total number of objects created each time is 3.

(Or, maybe it's still zero, or maybe it's millions. Remember that compilers and virtual machines are allowed to rewrite code for performance or implementation reasons, so long as its behavior is not otherwise changed. So it could delete the above code entirely if you don't use the result. Or if you try to print j, it could realize that j will always end up with the same constant value after the above snippet, and thus do all the arithmetic at compile time, and print a constant value. The actual amount of work done behind the scenes to run your code is always an implementation detail.)

Solution 5 - Java

You can debug the Integer.valueOf(int i) method to find out it by yourself. This method is called by the autoboxing process by the compiler.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSyamesh KView Question on Stackoverflow
Solution 1 - JavaBathshebaView Answer on Stackoverflow
Solution 2 - JavaStephen CView Answer on Stackoverflow
Solution 3 - JavaDenis LukenichView Answer on Stackoverflow
Solution 4 - JavaBoannView Answer on Stackoverflow
Solution 5 - JavaCootriView Answer on Stackoverflow