sizeOf() calculation from ClassLayout seems to be wrong

Volker Simonis volker.simonis at gmail.com
Tue Jun 7 08:59:17 UTC 2016


On Tue, Jun 7, 2016 at 2:47 AM, Enis Söztutar <enis.soz at gmail.com> wrote:
> Hi,
>
> I was testing ClassLayout with small byte[]'s, and noticed something with a
> byte[] size of 9:
>
> [B object internals:
>
>  OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
>
>       0     4       (object header)                01 00 00 00 (00000001
> 00000000 00000000 00000000) (1)
>
>       4     4       (object header)                00 00 00 00 (00000000
> 00000000 00000000 00000000) (0)
>
>       8     4       (object header)                f5 00 00 f8 (11110101
> 00000000 00000000 11111000) (-134217483)
>
>      12     4       (object header)                11 00 00 00 (00010001
> 00000000 00000000 00000000) (17)
>
>      16    17  byte [B.<elements>                  N/A
>
>      33     7       (loss due to the next object alignment)
>
> Instance size: 40 bytes
>
> Space losses: 0 bytes internal + 7 bytes external = 7 bytes total
>
> We seem to be calculating an extra 8 bytes in the byte[] layout after the
> header. The instance size is calculated as 40, however,
> VM.current().sizeOf() returns 32.

Hi Enis,

I'm not sure what ClassLayout is reporting, but after the header, an
array first has its length field (which is an int) and thereafter the
array elements begin on a 8-byte aligned address.

So if you're running without compressed oops you have the following layout:

(gdb) call find($r3)

"Executing find"
0x00003ffe3fe99458 is an oop
[B
{0x00003ffe3fe99458} - klass: {type array byte}
 - length: 9
 -   0: 1
 -   1: 2
 -   2: 3
 -   3: 4
 -   4: 5
 -   5: 6
 -   6: 7
 -   7: 8
 -   8: 9
(gdb)  x /12x $r3
0x3ffe3fe99458:    0x00000001    0x00000000    0x167007d0    0x00003ffe
0x3ffe3fe99468:    0x00000009    0x00000000    0x04030201    0x08070605
0x3ffe3fe99478:    0x00000009    0x00000000    0xbaadbabe    0xbaadbabe

The first 16 bytes are the object header. At address 0x3ffe3fe99468
you have the arrays size (9) and at 0x3ffe3fe99470 the start of the
array elements. Notice the you loose 4 bytes because the start of the
elements has to be 8-byte aligned. Also the array is padded with 4
bytes at the end to finish at a 8-byte aligned address. So in total
the array occupies 40 bytes in the heap.

With compressed oops, the layout looks as follows:

(gdb) call find($r3)

"Executing find"
0x00000000c3e1a928 is an oop
[B
{0x00000000c3e1a928} - klass: {type array byte}
 - length: 9
 -   0: 1
 -   1: 2
 -   2: 3
 -   3: 4
 -   4: 5
 -   5: 6
 -   6: 7
 -   7: 8
 -   8: 9
(gdb) x /12x $r3
0xc3e1a928:    0x00000001    0x00000000    0x200000fa    0x00000009
0xc3e1a938:    0x04030201    0x08070605    0x00000009    0x00000000
0xc3e1a948:    0xbaadbabe    0xbaadbabe    0xbaadbabe    0xbaadbabe

Now the object header is 12 bytes and the arrays length field fits
into the first 16 bytes. The array elements start at 0xc3e1a938 but
again they have to finish at an 8-byte aligned address so they are
padded with 4 bytes at the end. In total, the array occupies 32 bytes
in compressed oops mode.

Regards,
Volker

PS: gdb is your friend :) If you happen to be in Tallin the next days
you can come and hear
http://2016.geekout.ee/schedule/hotspot-debugging-at-the-os-level (or
watch an older version online:
https://www.youtube.com/watch?v=JZpEskA_89U)


>
>
> This little UT also fails with the latest source code base:
>
> public class ArraySizeTest {
>
>   @Test
>
>   public void testByteArraySize() {
>
>     System.err.println(VM.current().details()); // debug
>
>     for (int i = 0; i < 100; i++) {
>
>       byte[] b = new byte[i];
>
>       long vmSize = VM.current().sizeOf(i);
>
>       long clSize = ClassLayout.parseInstance(b).instanceSize();
>
>       Assert.assertEquals("sizeOf() from VM and ClassLayout does not match,
> VM.sizeOf()="
>
>         + vmSize + ", ClassLayout.instanceSize()=" + clSize, vmSize, clSize
> );
>
>     }
>
>   }
>
> }
>
> I was not able to open a JIRA issue for this, figured I can report here.
>
> Thanks,
>
> Enis


More information about the jol-dev mailing list