xea
xea

Reputation: 1214

Why do longs and doubles take up two entries in Java classes' constant pools?

The Java Virtual Machine Specification states that 8-byte (such as long and double) constants take up two entries in the constant_pool table, unlike other constants that take up only one entry each. The specification also mentions that it was a poor choice but doesn't explain why.

What was the original reason behind this design decision and what were the benefits at the time?

Upvotes: 8

Views: 867

Answers (3)

Peter Lawrey
Peter Lawrey

Reputation: 533530

They used 2 because that's what they decided when they designed it. There is no reason it has to be 2. There is no reason it's not 8 for 8 bytes. References are always 1 even though they could be 64-bit.

It made sense at the time to treat everything up to 32-bit as 32-bit and assume reference were 32-bit so long and double were double that but given it's a virtual machine it doesn't matter at all.

The performance difference either way is entirely notional.

The specification also mentions that it was a poor choice but doesn't explain why.

In hind sight, the simplest thing would have been to make it 1 slot for everything and not get involved in how the memory might be used at runtime. Note: the JVM can optimise away variables so they don't take any space at all.

Upvotes: 0

Antimony
Antimony

Reputation: 39451

A definitive answer would require talking to someone involved in the early development of Java. However, I think it is pretty clear that the bytecode format was originally designed with the performance of a naive interpreter in mind.

Consider how you would write a very simple Java bytecode interpeter. There's no JIT, no optimization, etc. You just execute each instruction as you get to it. Assuming the constant pool has been decoded to a table of 32 bit values at load time, an instruction like ldc2_w x, referencing the constant pool, would execute C code along the lines of

*(*int64)(stack_ptr += 8) = *(*int64)(constant_pool_ptr + x * 4)

Basically, if you are on a 32 bit machine, and are translating everything to raw pointer accesses with no optimization, then using two slots for 64 bit values is simply the logical way to implement things.

The reason it is a poor choice today is because nowadays, interpreters aren't completely unoptimized like this. In fact, code is usually JITed. Furthermore, 64 bit platforms are the norm, which means that reference types take up 64 bits anyway*, even though the specification treats them like 32 bit values. Therefore, there is no longer any benefit to this hack, but we still pay the cost in specification and implementation complexity.

^ Theoretically at least. The JVM uses 32 bit compressed pointers by default, even on 64 bit platforms, to reduce memory usage.

Upvotes: 3

arcy
arcy

Reputation: 13123

I do not know the actual answer, not having been involved with the design of Java and its virtual machine. I can make an educated guess.

The constant pool array is full of items that point to other items; if long and double constants had been pointed to instead of contained in the array, then they would not have needed to take up additional room.

Since they do take up an additional index, it means that every index into the array must be tested to see if it is the 'unusable' index after the index to the long or double. This slows down access to all elements of the array, significantly compared to only checking range.

From a software engineering point of view, it is also an unnatural way to use an array. Every single reference to this structure needs to contain a note about these indices, lest some additional code assume the array has a constant size per element (which is one of the natural assumptions about arrays).

Guessing further, it's possible someone thought it was a shame to occupy the space for a pointer to a structure that just needed a little bit more space, and so saved the space by including it in the array itself. They may even have thought that it was a more efficient way of using the long and double values, missing the fact that it slowed everything else down.

Upvotes: 0

Related Questions