Java has a couple of different options for dealing with objects but is able to manage the full set of pointers and know that (for example) code doesn&#x27;t try to access memory+1 for looping etc.<p>Under 4G worth of size pointers are simply zero extended, so that the higher order bits are just zero and the lower order bits stores in 32 bits.<p>Above 4G but below 32G it switches to &quot;compressed oops&quot; mode. This right-shifts the address by 3 bits and ensures&#x2F;mandates that all objects are aligned to 8 bits (2^3). When converting back again to a memory address it multiplies by 8. This effectively multiplies the top address space by a factor of 8 and so you can store an object in the same 32 bits but can be wider.<p>It&#x27;s possible to shift the alignment (-XX:ObjectAlignmentInBytes=16) which will then right shift the address by 4 instead giving you 64Gb memory with 32 bit addressing.<p>Although it&#x27;s possible to go higher the advantages tend to scale out; effectively you end up padding the object space more and more so simple objects take up larger and larger slots.<p>The bottom line is: by controlling where pointers are used, Java can use a different addressing scheme by unpacking and repacking object pointers on the fly. And for some operations (equality testing) it doesn&#x27;t even need to unpack the pointers in the first place.