Here is a link to the code in question - 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();
}
When I run the code as is I see the following:
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)
I am unsure where the 4952 bytes for [Ljava.lang.Object; is coming from. If I update the ArrayList creation and set a initial size to 1000 so that there is no growing I get the following:
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)
Thanks.
UPDATE
I turned off CompressedOops (-XX:-UseCompressedOops). Here is the new result:
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)
So when disabling CompressedOops the reference sizes increase to 8 bytes. To me that makes even more sense that the Object array holds the references to the 1000 Integer Objects.
ArrayList
internally is backed by an Object[]
as a buffer, which grows as needed.
An array of objects is actually an array of object references. In your case, it looks like each object reference is 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.
When you allow the ArrayList
to grow naturally, any unused indexes in the buffer array default to null
, which still uses 4 bytes of memory per index.
The ArrayList
that allows growth has probably expanded to (4952 - 16) / 4 = ~1234 capacity.
While the ArrayList
that doesn't require growth only has 1000 capacity.