Maximale Anzahl von Parametern in der Java-Methodendeklaration

133

Wie viele Parameter kann eine Methode in Java maximal haben und warum?

Ich verwende Java 1.8 auf einem 64-Bit-Windows-System.

Alle Antworten auf StackOverflow zu diesem Thema besagen, dass das technische Limit 255 Parameter beträgt, ohne anzugeben, warum.

Um genau zu sein, 255 für statische und 254 für nicht statische ( thisin diesem Fall 255.) Methoden.

Ich dachte, dies könnte in einer Art Spezifikation beschrieben werden und es gibt einfach eine statisch definierte maximale Anzahl von Parametern, die zulässig sind.

Dies galt jedoch nur für intalle 4-Byte-Typen . Ich habe einige Tests mit longParametern durchgeführt und konnte in diesem Fall nur 127 Parameter deklarieren.

Mit StringParametern ist die zulässige Zahl, die ich aus dem Testen abgeleitet habe, 255 (kann es sein, dass die Referenzgröße in Java 4 Byte beträgt?).

Da ich jedoch ein 64-Bit-System verwende, sollte die Referenzgröße 8 Byte breit sein, und daher sollte bei StringParametern die maximal zulässige Anzahl 127 betragen, ähnlich wie bei longTypen.

Wie wird diese Grenze genau angewendet?

Hat das Limit etwas mit der Stapelgröße der Methode zu tun ?

Hinweis: Ich werde diese vielen Parameter in keiner Methode wirklich verwenden, aber diese Frage dient nur dazu, das genaue Verhalten zu klären.

userv
quelle
39
7, wenn Sie nicht mit Lesbarkeit verrückt werden wollen. (Ich weiß, was Sie tatsächlich fragen).
Adam
14
Ich würde streiten <= 4. Alles andere sollte wahrscheinlich in ein Objekt eingewickelt werden.
Vivin Paliath
4
Warum ist das eine interessante Frage? Wenn Sie ein Programm schreiben und diese Grenze erreichen, ist Ihr Design falsch. Ich verstehe nicht, warum eine so praktisch nutzlose Frage so viele positive Stimmen bekommt.
Jesper
20
@Jesper, da diese Frage das Wissen über die JVM-Spezifikation in Frage stellt. Diese Frage fragt nicht "Wie macht man das oder das?" stattdessen fragt es "Warum brauche ich das?" ... +1 Interessante Frage Userv
Amit
2
@amit genau das, was ich dachte. Das OP war nur neugierig.
Evan Carslake

Antworten:

110

Diese Grenze ist in der JVM-Spezifikation definiert :

Die Anzahl der Verfahrensparameter ist auf 255 begrenzt , durch die Definition eines Methodendeskriptors (§4.3.3), wo die Grenze für eine Einheit umfasst dies im Fall von Beispiel oder Schnittstellenmethodenaufrufen.

Abschnitt §4.3.3 enthält einige zusätzliche Informationen:

Ein Methodendeskriptor ist nur gültig, wenn er Methodenparameter mit einer Gesamtlänge von 255 oder weniger darstellt, wobei diese Länge den Beitrag dazu bei Instanz- oder Schnittstellenmethodenaufrufen enthält.

Die Gesamtlänge wird berechnet, indem die Beiträge der einzelnen Parameter summiert werden. wobei ein Parameter vom Typ long oder double zwei Einheiten zur Länge beiträgt und ein Parameter eines anderen Typs eine Einheit beiträgt .

Ihre Beobachtungen waren genau richtig, Doppelwortprimitive ( long/double ) benötigen die doppelte Größe der üblichen 4-Byte-Variablen und 4-Byte-Objektinstanzreferenzen .

In Bezug auf den letzten Teil Ihrer Frage zu 64-Bit-Systemen definiert die Spezifikation, wie viele Einheiten ein Parameter beisteuert . Dieser Teil der Spezifikation muss auch auf einer 64-Bit-Plattform noch eingehalten werden. Die 64-Bit-JVM nimmt 255 Instanzparameter auf (wie Ihre 255) Strings) unabhängig von der Zeigergröße des internen Objekts.

Umberto Raimondi
quelle
10
Ich möchte dieser Antwort hinzufügen, dass bei einer 64-Bit-Architektur der Stapel auch 64-Bit ist. Da die Begrenzung der Parameteranzahl an die Stapelgröße gebunden ist, ermöglicht der 64-Bit-Stapel das Speichern derselben 255 Objektreferenzen. Die spezifische Behandlung longund doubleunabhängig von der Systemarchitektur findet an vielen Stellen der Spezifikation statt und scheint ein Überbleibsel der 32-Bit-Ära zu sein.
Sergei
Ich war gerade dabei, genau diesen Teil zu bearbeiten :) Einverstanden, die Spezifikation muss auch auf verschiedenen Plattformen noch eingehalten werden.
Umberto Raimondi
1
Ja, wenn die Anzahl der Parameter von der Wortgröße abhängt, würde dies die Portabilität beeinträchtigen. Sie konnten nicht dasselbe Java-Programm erfolgreich auf verschiedenen Architekturen kompilieren.
Vivin Paliath
3
Varargs wird in eine eingeObjektArray, kann nur ein einziges Mal in der Parameterliste und belegt die letzte Position verwendet werden. In Anbetracht all dessen würde ich sagen, dass mit varargs die Anzahl der Parameter auf 254 + Integer.MAX_VALUE "erweitert" werden kann (zumindest für den Programmierer ... Parameter sind immer noch 255), also können Sie mit diesem Trick Integer haben. MAX_VALUE Objektparameter.
Umberto Raimondi
1
@ MrTsjolder Schauen Sie sich diese Antwort für Varargs an.
Vivin Paliath
11

Abschnitt 4.3.3 der JVM-Spezifikation enthält die Informationen, nach denen Sie suchen:

Ein Methodendeskriptor ist nur gültig, wenn er Methodenparameter mit einer Gesamtlänge von 255 oder weniger darstellt, wobei diese Länge den Beitrag dazu bei Instanz- oder Schnittstellenmethodenaufrufen enthält. Die Gesamtlänge wird berechnet, indem die Beiträge der einzelnen Parameter summiert werden, wobei ein Parameter vom Typ long oder double zwei Einheiten zur Länge beiträgt und ein Parameter eines anderen Typs eine Einheit beiträgt .

Daher scheint es keinen Einfluss auf die Anzahl der Parameter zu haben, ob der Host-Computer 32-Bit oder 64-Bit ist. Wenn Sie bemerken, spricht die Dokumentation von "Einheiten", wobei die Länge einer "Einheit" eine Funktion der Wortgröße ist. Wenn die Anzahl der Parameter direkt proportional zur Wortgröße wäre, gäbe es Portabilitätsprobleme. Sie könnten nicht dasselbe Java-Programm auf verschiedenen Architekturen kompilieren (vorausgesetzt, mindestens eine Methode verwendet die maximale Anzahl von Parametern in der Architektur mit der größeren Wortgröße).

Vivin Paliath
quelle
10

Ich fand eine interessante Ausgabe aus einem Newsletter dazu, http://www.javaspecialists.eu/archive/Issue059.html

Der Konstantenpool pro Klasse oder pro Schnittstelle ist durch das 16-Bit-Feld constante_pool_count der ClassFile-Struktur auf 65535 Einträge beschränkt. Dies wirkt als interne Grenze für die Gesamtkomplexität einer einzelnen Klasse oder Schnittstelle. Die Codemenge pro nicht nativer, nicht abstrakter Methode ist durch die Größe der Indizes in der Ausnahmetabelle des Code-Attributs, im LineNumberTable-Attribut und im LocalVariableTable-Attribut auf 65536 Byte begrenzt.

Die größte Anzahl lokaler Variablen im Array lokaler Variablen eines Frames, der beim Aufruf einer Methode erstellt wurde, ist durch die Größe des Elements max_locals des Code-Attributs, das den Code der Methode angibt, auf 65535 begrenzt. Beachten Sie, dass Werte vom Typ long und double jeweils zwei lokale Variablen reservieren und zwei Einheiten zum Wert max_locals beitragen. Die Verwendung lokaler Variablen dieser Typen verringert diese Grenze also weiter.

Die Anzahl der Felder, die von einer Klasse oder Schnittstelle deklariert werden können, ist durch die Größe des Feldfelds_count-Elements der ClassFile-Struktur auf 65535 begrenzt. Beachten Sie, dass der Wert des Elements fields_count der ClassFile-Struktur keine Felder enthält, die von Oberklassen oder Superschnittstellen geerbt werden.

Matthew Brzezinski
quelle