Я могу прочитать в документации JVM следующее:

Все 8-байтовые константы занимают две записи в таблице constant_pool файла класса. Если структура CONSTANT_Long_info или CONSTANT_Double_info является элементом в таблице constant_pool с индексом n, то следующий используемый элемент в пуле располагается с индексом n + 2. Индекс constant_pool n + 1 должен быть действительным, но считается непригодным для использования.

Оглядываясь назад, можно сказать, что создание 8-байтовых констант, занимающих две записи в пуле констант, было плохим выбором.

Если индекс n + 1 действителен, как он может быть «непригодным для использования»? Кроме того, он не кажется полностью непригодным для использования, поскольку в нем можно сохранить значение:

Значение типа long или типа double занимает две последовательные локальные переменные. К такому значению можно обращаться только с использованием меньшего индекса. Например, значение типа double, хранящееся в массиве локальных переменных под индексом n, фактически занимает локальные переменные с индексами n и n + 1; однако локальная переменная с индексом n + 1 не может быть загружена из. Его можно хранить в формате. Однако это делает недействительным содержимое локальной переменной n.

Означает ли это, что «действительный» = «вы можете сохранить в нем» и «непригодный для использования» = «вы не можете его загрузить»?

2
Codoscope 9 Янв 2017 в 07:27

1 ответ

Лучший ответ

Вы смешиваете постоянный пул и локальные переменные.

Первая ссылка говорит о постоянном пуле, который, как следует из названия, является постоянным. Вы не можете хранить в постоянном пуле. Фраза « индекс constant_pool n + 1 должен быть действительным » подразумевает, например, что если последняя запись пула является константой long или double, вы все равно необходимо объявить пул достаточно большим, чтобы вместить обе записи, хотя вторая не может использоваться. Я не знаю каких-либо других практических последствий, так что это в основном формальное заявление, подразумевающее, что существует непрерывный диапазон действительных индексов, хотя по некоторым из них невозможно прочитать.

Другое дело - локальные переменные, о которых идет речь во второй цитате. Можно записывать локальные переменные, и записываемое значение не обязательно должно быть того же типа, что и предыдущее, единственное требование - чтобы последующие чтения соответствовали текущему типу переменной, то есть самому последнему записанному значению. Таким образом, вы можете писать в индекс n +1, даже если ранее было значение типа long или double в n , хотя это подразумевает что после этого нет допустимого значения в n , только новое значение в n +1.

2
Holger 9 Янв 2017 в 19:22
Имеет смысл, хотя я все еще не вижу смысла говорить, что индекс n + 1 должен быть действительным. В моем понимании существование этого индекса или непрерывность записей пула в памяти не имеет значения, если JVM ведет себя правильно.
 – 
Codoscope
9 Янв 2017 в 20:47
@ Qu'est-cet'yont Смысл того, что индекс n + 1 должен быть действительным, заключается в том, что у вас не может быть Long или Double с индексом n-1, где n - размер постоянного пула. Это должно быть не более n-2.
 – 
Antimony
9 Янв 2017 в 21:30
1
@Antimony: это просто другая формулировка для «объявить пул достаточно большим, чтобы вместить обе записи», но, похоже, нет других последствий, что действительно поднимает вопрос, почему они выбрали эту формулировку. Чтобы сделать это еще более запутанным, они используют другую «достоверность» в §4.1, где они говорят: « Индекс constant_pool считается действительным, если он больше нуля и меньше constant_pool_count, за исключением констант типа long и double, отмеченные в §4.4.5. », создавая впечатление, что эти константы могут вызывать недопустимые индексы. В общем, об этом выборе они все равно жалеют ...
 – 
Holger
9 Янв 2017 в 21:42