Попытка понять след ArrayList в JOLSample_16_AL_LL
Вот ссылка на рассматриваемый код - 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)
Я не уверен, где 4952 байта для [Ljava.lang.Object; идет от. Если я обновлю создание 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 байт. Для меня это имеет больше смысла, что массив Object содержит ссылки на 1000 Integer Objects.
1 ответ
ArrayList
внутренне поддерживается Object[]
в качестве буфера, который растет по мере необходимости.
Массив объектов на самом деле является массивом ссылок на объекты. В вашем случае, похоже, что каждая ссылка на объект составляет 4 байта, поэтому массив из них будет использовать 4 * length
байты, плюс некоторые накладные расходы, такие как длина массива и другие вещи.
Когда вы позволяете ArrayList
для естественного роста любые неиспользуемые индексы в массиве буферов по умолчанию null
, который по-прежнему использует 4 байта памяти на индекс.
ArrayList
что позволяет рост, вероятно, расширился до (4952 - 16) / 4 = ~ 1234 емкости.
В то время как ArrayList
который не требует роста, имеет только 1000 мощностей.