jol footprint of HashMap<Integer, Integer>

367 views Asked by At

I have a problem with objects footprint understanding:

I'm running the following lines in two cases A and B

out.println(VM.current().details());
HashMap<Integer, Integer> hashMap = new HashMap<>();
A:
    for (int i = 0; i < 1000; i++) {
        hashMap.put(i, i);
    }
B:
    for (int i = 0; i < 1000; i++) {
        hashMap.put(1000 + i, i);
    }

PrintWriter pw = new PrintWriter(out);
pw.println(GraphLayout.parseInstance(hashMap).toFootprint());

Case A result is:

java.util.HashMap@1f89ab83d footprint:
 COUNT       AVG       SUM   DESCRIPTION
     1      8208      8208   [Ljava.util.HashMap$Node;
  1872        16     29952   java.lang.Integer
     1        48        48   java.util.HashMap
  1000        32     32000   java.util.HashMap$Node
  2874               70208   (total)

Case B result is:

java.util.HashMap@1f89ab83d footprint:
 COUNT       AVG       SUM   DESCRIPTION
     1      8208      8208   [Ljava.util.HashMap$Node;
  2000        16     32000   java.lang.Integer
     1        48        48   java.util.HashMap
  1000        32     32000   java.util.HashMap$Node
  3002               72256   (total)

The difference between A and B is 128 instances of Integer (1872 vs 2000). The first assumption was an IntegerCache affects but it does not explain case B in my mind.

The question: why these two footprints are different?

details:

jol: "org.openjdk.jol:jol-core:0.8"

# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
...
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
1

There are 1 answers

0
Thomas On BEST ANSWER

Java indeed has a cache for Integer instances with values between -128 and 127 (when using auto-boxing or Integer.valueOf(int) directly). Thus put(i,i) will use the same instance whereas put(1000 + i, i) or even put(1000 + i, 1000 + i) won't.

put(i,i) will use the cache for values 0 to 127 (i.e. 128 instances) and return the same Integer instance in both cases.

put(1000 + i,i) will create a new Integer instance for the key but use the cache for values 0 to 127 (i.e. 128 instances)

put(1000 + i, 1000 + i) will create new Integer instances for both the key and the value even though they have the same numerical value. Thus if you'd do that you should see 128 additional Integer instance be created.