7

Suppose that I am in a 64-bit machine compiling a C program with gcc. I'm assuming that sizeof(int) is 8 bytes, and sizeof(char) is 1 byte.

Because of memory alignment, the following struct:

struct example{
    int a;
    char c;
}

does not actually have a size of 9 bytes, but 16 (twice sizeof(int)), so that both its beginning and ending addresses can be at multiples of the word size (assumed 8 bytes here).

I was wondering how large the following class would be in Java 8:

class Node {
    int val;
    Node left, right;
    boolean flag;
 }

I'm basically not certain whether we would align at multiples of 8 or 4 bytes.

Jason
  • 2,495
  • 4
  • 26
  • 37

2 Answers2

17

You can use jol to know the exact layout of objects. This is the output of the program for your Node class (on Oracle JDK 1.8.0_121 64 bit):

# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

org.example.Node 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)                70 22 01 f8 (01110000 00100010 00000001 11111000) (-134143376)
    12     4     int Node.val                       0
    16     1 boolean Node.flag                      false
    17     3         (alignment/padding gap)        N/A
    20     4    Node Node.left                      null
    24     4    Node Node.right                     null
    28     4         (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 3 bytes internal + 4 bytes external = 7 bytes total

So, the alignment is 8 bytes.

Note, this is platform-specific. You shouldn't rely much on this information.

ZhekaKozlov
  • 36,558
  • 20
  • 126
  • 155
  • Ah, the alignment information is right there. Excellent, thanks! – Jason Jun 10 '17 at 03:08
  • 1
    It would be useful to include the commands used. I can follow the linked docs to make it work for JDK classes, but trying to reproduce this for a simple .class file like Node I get `ClassNotFoundException`. Puzzled. – Luke Usherwood Aug 16 '18 at 07:07
  • @LukeUsherwood Did you see [this](http://hg.openjdk.java.net/code-tools/jol/file/03064c057dc9/jol-samples/src/main/java/org/openjdk/jol/samples/JOLSample_02_Alignment.java)? I used Java 8. – ZhekaKozlov Aug 20 '18 at 04:44
  • I'd browsed a few examples but had the impression you could do it on the command-line as per the examples in the "Use as Command Line Tool" section of the linked wiki. (I couldn't find a flag like `-cp` so I thought maybe if the working directory was set appropriately...) So you wrote code and printed this data programmatically then, I take it? – Luke Usherwood Aug 21 '18 at 12:59
  • 1
    I created comparable tables using `java -cp "jol-cli-0.9-full.jar:." org.openjdk.jol.Main internals package.ClassUnderTest`. I am a bit puzzled with the results: Seeing above it was executed on a 64bit machine/jvm. Classes seem to be aligned to word size (8 bytes). Primitives are not aligned at all. And references are aligned to half words (4 bytes). Is that really the case? – steve Dec 07 '18 at 10:46
4

ZhekaKozlov's answer is not correct.

In Hotspot JVM on JDK8 at least, the alignment is 8 bytes by default, whether it's 32-bit JVM or 64-bit.

(Sorry I don't have enough reps to comment, so I have to post a new answer )

Tried on Oracle jdk-8u251 x86 version,

You can try starting your (Hotspot) JVM with the option XX:ObjectAlignmentInBytes=4, and it will fail with error:

ObjectAlignmentInBytes=4 must be greater or equal 8

Interesting sidenote, if you set it as 9, it will also complain that the number must be power of 2.

Also run this code snippet on the JVM above without any explicit VM option set, using jol,

System.out.println(VM.current().details());

it will print

# Running 32-bit HotSpot VM.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

Do note that the alignment size is not defined in JVM specification so it might vary by implementation.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
AwesomeHunter
  • 690
  • 6
  • 10
  • 1
    You are absolutely right. The object alignment is never less than 8 bytes on 32-bit JVM too. This is explained [here](https://shipilev.net/jvm/objects-inside-out/#_object_alignment). I fixed my answer. – ZhekaKozlov Nov 17 '20 at 11:16