Максимальное количество параметров в объявлении метода Java - программирование

Максимальное количество параметров в объявлении метода Java

Каково максимальное количество параметров, которые может иметь метод в Java и почему?

Я использую Java 1.8 в 64-разрядной системе Windows.

Все ответы на StackOverflow об этом говорят, что технический предел - 255 параметров без указания причины.

Чтобы быть точным, 255 для статического и 254 для нестатического (this будет 255-м в этом случае) методов.

Я думал, что это может быть описано в какой-то спецификации и что существует просто статически определенное максимальное количество разрешенных параметров.

Но это было справедливо только для int и всех 4-байтных типов. Я провел несколько тестов с параметрами long, и в этом случае я смог объявить 127 параметров.

С параметрами String допустимое число I, выведенное из теста, равно 255 (может быть, потому, что размер ссылки составляет 4 байта в Java?).

Но поскольку я использую 64-битную систему, размер ссылок должен быть 8 байтов в ширину, поэтому с параметрами String максимальное допустимое число должно быть 127, похожее на типы long.

Как этот предел точно применяется?

Ограничение имеет какое-либо отношение к размеру стека метода?

Примечание. Я не собираюсь использовать эти многие параметры в любом методе, но этот вопрос должен только прояснить точное поведение.

4b9b3361

Ответ 1

Этот предел определен в Спецификации JVM:

Число параметров метода ограничено 255 по определению дескриптора метода (п. 4.3.3), где предел включает в себя одну единицу для этого в случае вызова метода экземпляра или интерфейса.

Раздел §4.3.3 содержит дополнительную информацию:

Дескриптор метода действителен только в том случае, если он представляет параметры метода с общей длиной 255 или менее, причем эта длина включает в себя вклад для этого в случае вызова метода экземпляра или интерфейса.

Общая длина вычисляется путем суммирования вкладов отдельных параметров , где параметр типа long или double вносит два блока в длину, а параметр любого другого типа вносит один элемент.

Ваши наблюдения были точными, двойные словарные примитивы (long/double) нуждались в удвоении размера обычных 4 байтовых переменных и 4 байта ссылки на экземпляр объекта.

Относительно последней части вашего вопроса, относящейся к 64-битным системам, спецификация определяет, сколько единиц вводит параметр, что часть спецификации должна выполняться даже на 64-битной платформе, 64-битная JVM будет вмещать 255 параметров экземпляра (например, 255 Strings) независимо от внутреннего размера указателя объекта.

Ответ 2

Раздел 4.3.3 спецификации JVM содержит информацию, которую вы ищете:

Дескриптор метода действителен только в том случае, если он представляет параметры метода с общей длиной 255 или менее, причем эта длина включает в себя вклад для этого в случае вызова метода экземпляра или интерфейса. Суммарная длина вычисляется путем суммирования вкладов отдельных параметров, где параметр типа long или double вносит две единицы в длину, а параметр любого другого типа вносит один элемент.

Следовательно, похоже, что хост-машина 32-разрядная или 64-битная не влияет на количество параметров. Если вы заметили, документация говорит в терминах "единиц", где длина одной "единицы" зависит от размера слова. Если количество параметров, прямо пропорциональных размеру слова, будут проблемы с переносимостью; вы не сможете скомпилировать одну и ту же программу Java на разных архитектурах (предполагая, что хотя бы один метод использовал максимальное количество параметров в архитектуре с большим размером слова).

Ответ 3

Я нашел интересный вопрос из информационного бюллетеня об этом, http://www.javaspecialists.eu/archive/Issue059.html

Пул констант для каждого класса или каждого интерфейса ограничен 65535 элементами по 16-битовому полю константы_пути_класса структуры ClassFile. Это действует как внутренний предел общей сложности одного класса или интерфейса. Количество кода для не-родного, не абстрактного метода ограничено 65536 байтами по размерам индексов в таблице exception_table атрибута Code, в атрибуте LineNumberTable и в атрибуте LocalVariableTable.

Наибольшее количество локальных переменных в массиве локальных переменных фрейма, созданного при вызове метода, ограничено 65535 размером элемента max_locals атрибута Code, предоставляющего код метода. Обратите внимание, что значения типа long и double считаются зарезервированными для двух локальных переменных и вносят две единицы в значение max_locals, поэтому использование локальных переменных этих типов еще больше уменьшает этот предел.

Число полей, которые могут быть объявлены классом или интерфейсом, ограничено размером 65535 по размеру элемента fields_count структуры ClassFile. Обратите внимание, что значение элемента fields_count в структуре ClassFile не включает поля, которые унаследованы от суперклассов или суперинтерфейсов.