Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What would happen if I were to make more references to Objects than 32 bits can account for?

So I just learned when you declare a variable of type Object ( i.e. Object a; ), a 32-bit space is allocated for that variable. Inside this variable/reference, there is a memory address to an actual Object.

Now let's pretend I have a large enough amount of memory to do this.

What would happen if I created more than 4,294,967,296 (232) variables of type Object and tried assigning them to a distinct Object? Would some variables/references get the same memory addresses due to integer overflow? Meaning it's impossible to have references to more than 4,294,967,296 Objects in memory?

like image 590
Kacy Raye Avatar asked Jul 15 '13 02:07

Kacy Raye


1 Answers

So I just learned when you declare a variable of type Object ( i.e. Object a; ), a 32-bit space is allocated for that variable. Inside this variable/reference, there is a memory address to an actual Object.

(When you talk about "a 32-bit space", IT folks will immediately think you are referring to an address space ... and a 32-bit address space gives you 2^32 bytes of storage!!)

So assuming that you actually mean "32 bits of space" what you are saying might be right, or it might be wrong. For a 32-bit JVM, references are indeed 32 bits long, and that means that your program can (in theory) refer to at most 2^32 distinct objects, of any kind. Even representing 2^32 distinct (32-bit) references will take 2^34 bytes.

On the other hand, if you are running your program on a 64-bit JVM, the size of a reference is 64-bits, and that means your program can (in theory) refer up to 2^64 distinct objects.

But this is all theoretical. The problem is that on a 32-bit machine, your program won't have enough memory to represent that many distinct objects. A minimal Java object on a 32-bit machine occupies (at least) 8 bytes. So even if you have the entire address space available you'd only be able to represent 2^29 objects. And in practice the OS doesn't provide the JVM that much memory. Indeed, depending on the OS, it may get at most 2 to 3Gb of the possible 4Gb of address space.


Of course, if you run a 64-bit JVM (on a 64-bit OS / and 64-bit capable hardware), you have a larger space for your object references AND you can have more memory to represent them. But you are still going to "hit the wall" eventually ... due to hardware limitations.

It is worth noting that Java has a variety of other inherent limits too. For instance, arrays can have at most 2^31 elements, Strings can have at most 2^31 characters, String literals are limited to 2^16 characters, and so on. These limits more fundamental than the 32 vs 64 bit reference limit.


FOLLOWUP

So to make long stories short, there will always be a pre-determined wall no matter how much memory I force my operating system to dedicate to my program at compile time ?

That is correct. (Sort of. You can't force the OS to dedicate memory to your program at compile time. The memory size is determined when you launch the program, not when you compile it.) Basically, you have the following "knobs" to twiddle ... at program launch time:

  • The JVM (32 vs 64 bit) places a bound on the amount of memory that is addressable, and determines whether references are 32 or 64 bits. (Note that this is a runtime choice. Compiled bytecode files are identical for 32 and 64 bit.)

  • The -Xms and -Xmx say how big the heap should be ... subject to the constraints of addressability and the amount of memory that the OS is prepared to give the JVM process.

  • There is also a Compressed OOPS feature that is relevant for a 64-bit JVM, but it is typically on by default.

like image 177
Stephen C Avatar answered Oct 04 '22 21:10

Stephen C