试图了解 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个容量。
这里是有问题的代码的 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个容量。