Search code examples
javajvmbytecodejvm-bytecode

Valid unusable constant pool index


I can read in the JVM documentation the following:

All 8-byte constants take up two entries in the constant_pool table of the class file. If a CONSTANT_Long_info or CONSTANT_Double_info structure is the item in the constant_pool table at index n, then the next usable item in the pool is located at index n+2. The constant_pool index n+1 must be valid but is considered unusable.

In retrospect, making 8-byte constants take two constant pool entries was a poor choice.

If the index n+1 is valid, how can it be "unusable"? Additionally, it doesn't seem to be completely unusable since it's possible to store a value into it:

A value of type long or type double occupies two consecutive local variables. Such a value may only be addressed using the lesser index. For example, a value of type double stored in the local variable array at index n actually occupies the local variables with indices n and n+1; however, the local variable at index n+1 cannot be loaded from. It can be stored into. However, doing so invalidates the contents of local variable n.

Does it mean that "valid" = "you can store into it", and "unusable" = "you can't load it"?


Solution

  • You are mixing up the constant pool and local variables.

    The first cite talks about the constant pool, which is, as the name suggests, constant. You can’t store into the constant pool. The phrase “the constant_pool index n+1 must be valid” implies, for example, that if the last entry of the pool is a long or double constant, you still have to declare the pool big enough to hold both entries, though the second isn’t usable. I don’t know of any other practical consequences, so it’s mainly a formal statement implying that there is a contiguous range of valid indices, though some of them can’t be read from.

    Local variables, which your second cite is about, are a different thing. Local variables can be written and the value being written doesn’t need to be the same type as the previous, the only requirement is that subsequent reads are appropriate for the current type of the variable, i.e. the most recently written value. So you can write to the index n+1 even when there previously was a value of type long or double at n, though that implies that there is no valid value at n afterwards, only the new value at n+1.