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]
Java indeed has a cache for
Integer
instances with values between -128 and 127 (when using auto-boxing orInteger.valueOf(int)
directly). Thusput(i,i)
will use the same instance whereasput(1000 + i, i)
or evenput(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 sameInteger
instance in both cases.put(1000 + i,i)
will create a newInteger
instance for the key but use the cache for values 0 to 127 (i.e. 128 instances)put(1000 + i, 1000 + i)
will create newInteger
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 additionalInteger
instance be created.