我在理解对象足迹方面遇到问题:
我在两种情况 A 和 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());
案例 A 结果为:
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)
案例 B 的结果是:
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)
A 和 B 之间的差异是整数的 128 个实例(1872 与 2000(。第一个假设是影响IntegerCache
,但它并不能解释我脑海中的案例B。
问题是:为什么这两个脚印不同?
详:
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确实有一个缓存,用于Integer
值在-128和127之间的实例(当使用自动装箱或直接Integer.valueOf(int)
时(。因此,put(i,i)
将使用相同的实例,而put(1000 + i, i)
甚至put(1000 + i, 1000 + i)
不会。
put(i,i)
将使用值 0 到 127(即 128 个实例(的缓存,并在这两种情况下返回相同的 Integer
实例。
put(1000 + i,i)
将为密钥创建一个新的Integer
实例,但对值 0 到 127(即 128 个实例(使用缓存
put(1000 + i, 1000 + i)
将为键和值创建新的Integer
实例,即使它们具有相同的数值。因此,如果您这样做,您应该会看到创建了 128 个额外的Integer
实例。