试图了解 ArrayList 在 JOLSample_16_AL_LL 中的足迹

Trying to understand the footprint of ArrayList in JOLSample_16_AL_LL

这里是有问题的代码的 link - http://hg.openjdk.java.net/code-tools/jol/file/07087260ce41/jol-samples/src/main/java/org/openjdk/jol/samples/JOLSample_16_AL_LL.java

public static void main(String[] args) throws Exception {
    out.println(VM.current().details());

    List<Integer> al = new ArrayList<Integer>();
    List<Integer> ll = new LinkedList<Integer>();

    for (int i = 0; i < 1000; i++) {
        Integer io = i; // box once
        al.add(io);
        ll.add(io);
    }

    PrintWriter pw = new PrintWriter(out);
    pw.println(GraphLayout.parseInstance(al).toFootprint());
    pw.println(GraphLayout.parseInstance(ll).toFootprint());
    pw.println(GraphLayout.parseInstance(al, ll).toFootprint());
    pw.close();
}

当我按原样 运行 代码时,我看到以下内容:

java.util.ArrayList@5f205aad footprint:
     COUNT       AVG       SUM   DESCRIPTION
         1      4952      4952   [Ljava.lang.Object;
      1000        16     16000   java.lang.Integer
         1        24        24   java.util.ArrayList
      1002               20976   (total)

我不确定 [Ljava.lang.Object 的 4952 字节在哪里;来自。如果我更新 ArrayList 创建并将初始大小设置为 1000,这样就不会增长,我会得到以下结果:

java.util.ArrayList@5f205aad footprint:
 COUNT       AVG       SUM   DESCRIPTION
     1      4016      4016   [Ljava.lang.Object;
  1000        16     16000   java.lang.Integer
     1        24        24   java.util.ArrayList
  1002               20040   (total)

谢谢。

更新

我关闭了 CompressedOops (-XX:-UseCompressedOops)。这是新结果:

java.util.ArrayList@1996cd68d footprint:
 COUNT       AVG       SUM   DESCRIPTION
     1      8024      8024   [Ljava.lang.Object;
  1000        24     24000   java.lang.Integer
     1        40        40   java.util.ArrayList
  1002               32064   (total)

因此,当禁用 CompressedOops 时,引用大小会增加到 8 个字节。对我来说,对象数组包含对 1000 个整数对象的引用更有意义。

ArrayList 内部由 Object[] 作为缓冲区支持,grows as needed.

一个对象数组实际上是一个对象引用数组。在您的情况下,每个对象引用看起来都是 4 bytes, so an array of them would use 4 * length bytes, plus some overhead such as the length of the array and other stuff.

当您允许 ArrayList 自然增长时,缓冲区数组中任何未使用的索引默认为 null,每个索引仍使用 4 个字节的内存。

允许 增长的ArrayList 可能已扩展到 (4952 - 16) / 4 = ~1234 容量

而不需要增长的ArrayList只有1000个容量