22

I know that Java uses padding; objects have to be a multiple of 8 bytes. However, I dont see the purpose of it. What is it used for? What exactly is its main purpose?

Nando
  • 358
  • 3
  • 13

3 Answers3

20

Its purpose is alignment, which allows for faster memory access at the cost of some space. If data is unaligned, then the processor needs to do some shifts to access it after loading the memory.

Additionally, garbage collection is simplified (and sped up) the larger the size of the smallest allocation unit.

It's unlikely that Java has a requirement of 8 bytes (except on 64-bit systems), but since 32-bit architectures were the norm when Java was created it's possible that 4-byte alignment is required in the Java standard.

U2EF1
  • 12,907
  • 3
  • 35
  • 37
  • I found this information on [Wikipedia](http://en.wikipedia.org/wiki/Java_performance#Memory_usage) and [Javamex](http://www.javamex.com/tutorials/memory/object_memory_usage.shtml) saying that it is 8 bytes. But the only purpose is for garbage collection? – Nando Aug 12 '12 at 23:00
  • 2
    @user1110725, please read carefully. Alignment is not only meant for garbage collection but for memory access in general. – cyroxx Aug 12 '12 at 23:15
  • should be accpeted +1 – Ahmad Dwaik 'Warlock' Oct 08 '13 at 09:10
  • 2
    The Java standard does not require any alignment and it would be strange if the specification nailed down such an implementation detail. Sun’s implementations used 8 byte alignments pretty much from the beginning, which shouldn’t come at a surprise as such an alignment was state of the art in most operating system’s memory management as well. Even the good old Amiga500’s operating system uses 8 byte alignment for memory allocations. – Holger Jun 07 '16 at 18:24
  • @Holger why is 8 byte alignment regarded as state of the art? Is there any obvious benenits? – choxsword Sep 12 '21 at 13:03
  • 1
    @scottxiao there are different reasons, depending on how the memory management is implemented, but it usually boils down to a compromise between memory maintenance expenses and the loss due to the alignment. In the old Amiga’s operating system, for example, it meant, when an application releases memory, the fragment must be at least eight bytes, large enough to hold a pointer to the next free fragment and the size of the fragment. In the nineties, 64 bit data bus transfers were common enough to demand the alignment. Today, 8 byte alignment allows the JVM to address 32GB with a 32 bit pointer. – Holger Sep 13 '21 at 06:54
9

The accepted answer is speculation (but partially correct). Here is the real answer.

First of, to @U2EF1's credit, one of the benefits of 8-byte boundaries is that 8-bytes are the optimal access on most processors. However, there was more to the decision than that.

If you have 32-bit references, you can address up to 2^32 or 4 GB of memory (practically you get less though, more like 3.5 GB). If you have 64-bit references, you can address 2^64, which is terrabytes of memory. However, with 64-bit references, everything tends to slow down and take more space. This is due to the overhead of 32-bit processors dealing with 64-bits, and on all processors more GC cycles due to less space and more garbage collection.

So, the creators took a middle ground and decided on 35-bit references, which allow up to 2^35 or 32 GB of memory and take up less space so to have the same performance benefits of 32-bit references. This is done by taking a 32-bit reference and shifting it left 3 bits when reading, and shifting it right 3 bits when storing references. That means all objects must be aligned on 2^3 boundaries (8 bytes). These are called compressed ordinary object pointers or compressed oops.

Why not 36-bit references for accessing 64 GB of memory? Well, it was a tradeoff. You'd require a lot of wasted space for 16-byte alignments, and as far as I know the vast majority of processors receive no speed benefit from 16-byte alignments as opposed to 8-byte alignments.

Note that the JVM doesn't bother using compressed oops unless the maximum memory is set to be above 4 GB, which it does not by default. You can actually enable them with the -XX:+UsedCompressedOops flag.

This was back in the day of 32-bit VMs to provide the extra available memory on 64-bit systems. As far as I know, there is no limitation with 64-bit VMs.

Source: Java Performance: The Definitive Guide, Chapter 8

Matt Quigley
  • 7,614
  • 4
  • 25
  • 26
  • 4
    The decision for 8-byte alignment is much older than the compressed oops feature and applies to 32Bit JVMs as well, which don’t support more than 2GB. Your speculation that “*future JVMs will support 64-bit references*” makes no sense, as all 64 bit JVMs *do* support 64-bit references. They are used when the heap is larger than 32GB or when specifying `-XX:-UsedCompressedOops` or when using an older JVM, which doesn’t have the compressed oops feature. – Holger Jun 07 '16 at 18:19
  • Perhaps poorly worded, but I meant references that use _all_ 64-bits, not that there weren't "references stored in 64-bit values". The last time I checked (which was a while ago), you could not use a 2^64 memory heap in a JVM. – Matt Quigley Jun 08 '16 at 19:12
  • 1
    I would be very surprised, if you ever find a real system (hardware+operating system) that supports allocating 2⁶⁴ bytes. I’m wondering, whether you understand, how big that is. However, you can use a heap as large as the underlying system supports it. If you think, you encountered a 64Bit JVM supporting less than the operating system allows, you have to be more specific. – Holger Jun 08 '16 at 20:04
  • Right. The source was written from the point of view of a 32-bit system, and I'm going to edit the answer to clarify. – Matt Quigley Jun 10 '16 at 05:37
  • 3
    Just to clarify: true 64 bit pointers were the norm, when 64 bit JVMs were introduced (back in jdk1.4). 32 bit JVMs don’t support more than 2GB heap size. So when you wanted more than 2GB heap, you had to use a 64 bit JVM and live with the higher memory consumption due to the bigger pointers. Then, back in Java 6, compressed oops were added as an optimization feature, to allow using smaller pointers when the heap is smaller than 32GB. It always was an optional feature which you can turn off. – Holger Jun 10 '16 at 09:32
  • 1
    By the way, recent JVMs have the `-XX:ObjectAlignmentInBytes` option, allowing values between `8` and `256`, so you may use compressed oops even with heaps bigger than 32GB, but the question is, whether the small pointers compensate the waste of memory caused by a bigger alignment… – Holger Jun 10 '16 at 09:35
  • @Holger You said "The decision for 8-byte alignment is much older [...] and applies to 32Bit JVMs as well". I can't find any reason why 8B alignment would make sense on an 32b system. Do you know why 32b HotSpot uses 8B alignment? Why would that be more efficient? Just for GC reasons? – spilot May 29 '17 at 23:37
  • 1
    @spilot: Assuming that the first JVMs didn’t have copying collectors, it was a trade-off between the amount of memory that might be unused due to the padding and the maintenance of the free memory blocks (or the possible fragmentation), but it’s also possible that the developers simply used the same alignment as the operating system, which had to make such a trade-off, which made 8B alignment simply state-of-the-art at that time (dating back at least to the middle of the 80s, if not earlier, as I remember 1986 AmigaOS using 8B alignment already). – Holger May 30 '17 at 09:12
  • @Holger: But why would an OS "have to make such a trade-off"? Which reason is there (except GC, which is nonexistent on OS level) for an alignment granularity larger than the largest piece of data (4B on 32b) a CPU can load with a single instruction? Can you recommend any book or paper on the subject? – spilot May 30 '17 at 09:21
  • 2
    @spilot: as said, *fragmentation*, to name one example. Since there is no GC, there is no such thing as a copying collector and no compacting, hence, freeing objects/data structures in a different order than allocating leaves holes of free memory, which have to be tracked and reassigned, if a subsequent allocation request fits in. One strategy would be to store the necessary information within the free memory itself, so 8 bytes are just enough to hold the size of the free memory block and the pointer to the next free block, on a 32 bit system. – Holger May 30 '17 at 09:30
  • 2
    @spilot there's some discussion about Alignment and other considerations in the Garbage Collection Handbook (p. 97). – Juraj Martinka Jul 01 '19 at 08:20
-2

Data type sizes in Java are multiples of 8 bits (not bytes) because word sizes in most modern processors are multiples of 8-bits: 16-bits, 32-bits, 64-bits. In this way a field in an object can be made to fit ("aligned") in a word or words and waste as little space as possible, taking advantage of the underlying processor's instructions for operating on word-sized data.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • 5
    Nope, bytes. Most (all?) JVM's align their data to at least 4 byte boundaries, except for small primitives in arrays. – U2EF1 Aug 12 '12 at 22:49
  • I'm not talking about datatypes, but object. With that I mean, my own objects. They are always a multiple of 8 bytes. At least, that is what I read. I found this information on [Wikipedia](http://en.wikipedia.org/wiki/Java_performance#Memory_usage) and [Javamex](http://www.javamex.com/tutorials/memory/object_memory_usage.shtml). – Nando Aug 12 '12 at 22:58