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


133

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

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

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

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

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

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

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

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

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

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

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


39
7, если вы не хотите сходить с ума с удобочитаемостью. (Я знаю, что вы на самом деле спрашиваете).
Адам

14
Я бы поспорил <= 4. Что-то еще, вероятно, должно быть заключено в объект.
Вивин Палиат

4
Почему это интересный вопрос? Если вы пишете программу и достигаете этого предела, значит, ваш дизайн неправильный. Я не понимаю, почему такой практически бесполезный вопрос получает столько голосов.
Jesper

20
@Jesper, потому что это ставит под сомнение знание спецификации JVM. Этот вопрос не задает вопрос «Как сделать то или иное?» вместо этого он спрашивает «Зачем мне это нужно?» ... +1 Интересный вопрос Усерв
Амит

2
@amit именно то, что я думал. ОП просто заинтересовался этим.
Эван Карслэйк

Ответы:


110

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

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

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

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

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

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

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


10
Я бы добавил к этому ответу, что в 64-битной архитектуре стек также является 64-битным. Таким образом, поскольку ограничение на количество параметров ограничено размером стека, 64-битный стек позволяет хранить те же 255 ссылок на объекты. Специфическая обработка longи doubleнезависимо от системной архитектуры происходит во многих местах спецификации и кажется остатком 32-битной эры.
Сергей

Я занимался редактированием только этой части :) Согласен, спецификацию все же следует уважать даже на разных платформах.
Умберто Раймонди,

1
Да, если бы количество параметров было функцией размера слова, это нарушило бы переносимость; Вы не могли успешно скомпилировать одну и ту же программу Java на разных архитектурах.
Vivin Paliath 01

3
Varargs превращаются в массив Object , могут использоваться только один раз в списке параметров и занимают последнюю позицию. Учитывая все это, я бы сказал, что с помощью varargs число параметров может быть «расширено» до 254 + Integer.MAX_VALUE (по крайней мере, для программиста ... параметры по-прежнему 255), поэтому, используя этот трюк, вы можете получить Integer. Параметры объекта MAX_VALUE.
Умберто Раймонди,

1
@MrTsjolder Взгляните на этот ответ для varargs.
Вивин Палиат

11

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

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

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


10

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

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.