Максимальна кількість параметрів у декларації методу 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 Цікаве запитання Userv
Аміт

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

3
Вараги, перетворені в масив об'єктів , можуть використовуватися лише один раз у списку параметрів і займати останнє місце. Враховуючи все це, я б сказав, що за допомогою varargs кількість параметрів можна "розширити" до 254 + Integer.MAX_VALUE (принаймні для програміста ... параметри все ще 255), тому використовуючи цей трюк, ви можете мати Integer. MAX_VALUE параметрів об'єкта.
Umberto Raimondi

1
@MrTsjolder Подивіться на цю відповідь для варагів.
Vivin Paliath

11

Розділ 4.3.3 специфікації JVM містить інформацію, яку ви шукаєте:

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

Тому виявляється, що хост-машина 32-бітна або 64-бітна не впливає на кількість параметрів. Якщо ви помітили, документація говорить в термінах "одиниці", де довжина однієї "одиниці" є функцією слова-розміру. Якщо кількість параметрів прямо пропорційна розміру слова, виникають проблеми з переносом; ви не зможете скласти одну і ту ж програму Java для різних архітектур (якщо принаймні один метод використовував максимальну кількість параметрів в архітектурі з більшим розміром слова).


10

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

Постійний пул для кожного класу або інтерфейсу обмежений 65535 записом 16-бітовим полем постійного_пункту_лінії структури ClassFile. Це виступає внутрішнім обмеженням на загальну складність одного класу чи інтерфейсу. Кількість коду на ненормативний, не абстрактний метод обмежена 65536 байтами за розмірами індексів у винятковому таблиці атрибута Code, у атрибуті LineNumberTable та атрибуті LocalVariableTable.

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

Кількість полів, які можуть бути оголошені класом або інтерфейсом, обмежена 65535 розміром елемента_поля_складу структури ClassFile. Зауважте, що значення елемента_полі_поліції структури ClassFile не включає поля, успадковані від надкласових чи надінтерфейсів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.