Максимальное количество параметров в объявлении метода 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
.
Как этот предел точно применяется?
Ограничение имеет какое-либо отношение к размеру стека метода?
Примечание. Я не собираюсь использовать эти многие параметры в любом методе, но этот вопрос должен только прояснить точное поведение.
Ответы
Ответ 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 не включает поля, которые унаследованы от суперклассов или суперинтерфейсов.