Maximale Größe einer Methode in Java 7 und 8

80

Ich weiß, dass eine Methode mit Java nicht größer als 64 KB sein kann. Die Einschränkung verursacht Probleme mit generiertem Code aus einer JavaCC- Grammatik. Wir hatten Probleme mit Java 6 und konnten dies durch Ändern der Grammatik beheben. Wurde das Limit für Java 7 geändert oder ist es für Java 8 geplant?

Nur um es klar zu machen. Ich brauche keine Methode, die größer als 64 KB ist. Aber ich habe eine Grammatik geschrieben, die nach einer sehr großen Methode kompiliert wird.

LaurentG
quelle
4
Ich hatte das gleiche Problem, als ich versuchte, einen riesigen Brainf ** k-Code zu kompilieren.
Johnchen902
3
Da keine gegenteiligen Informationen vorliegen, kann man davon ausgehen, dass dieses Limit in Java 8 weiterhin durchgesetzt wird. Eine andere (kostspielige) Option könnte natürlich darin bestehen, die Grammatik-Engine für parboiled zu ändern , was Ihnen dies ermöglicht Schreiben Sie Ihre Grammatiken in reinem Java.
fge
4
Schauen Sie sich diesen Artikel an
Anirudha
7
Persönlich denke ich, dass das Erstellen so großer Methoden ein Fehler in JavaCC ist . Es sollte wirklich in der Lage sein, seinen Code zu verbreiten. Vor allem, wenn man bedenkt, dass die JVM definitiv nicht für die Optimierung derart großer Methoden ausgelegt ist.
Joachim Sauer

Antworten:

58

Laut JVMS7 :

Die Tatsache, dass end_pc exklusiv ist, ist ein historischer Fehler beim Entwurf der Java Virtual Machine: Wenn der Java Virtual Machine-Code für eine Methode genau 65535 Byte lang ist und mit einem Befehl endet, der 1 Byte lang ist, kann dieser Befehl nicht geschützt werden von einem Ausnahmebehandler. Ein Compiler-Writer kann diesen Fehler umgehen, indem er die maximale Größe des generierten Java Virtual Code-Codes für eine Methode, eine Instanzinitialisierungsmethode oder einen statischen Initialisierer (die Größe eines beliebigen Code-Arrays) auf 65534 Byte begrenzt.

Aber das ist ungefähr Java 7. Es gibt keine endgültigen Spezifikationen für Java 8, daher konnte niemand (außer seinen Entwicklern) diese Frage beantworten.

UPD (2015-04-06) Laut JVM8 gilt dies auch für Java 8.

Andremoniy
quelle
2
Wirklich gibt es einen solchen "Fehler" in Java, dass er immer noch nicht behoben ist? Könnte eine starke Einschränkung sein, insbesondere für die LaurentG-Situation.
Francesco Belladonna
3
@ Fire-Dragon-DoL In der zitierten Diskussion geht es nur darum, dass die Methode ein Byte weniger lang sein muss, als es sonst hätte sein können. Das ist ziemlich unerheblich. Das Limit ist nicht auf einen einfachen "Fehler" wie diesen zurückzuführen: Es liegt im Gesamtdesign des Bytecodes, und um ihn zu beheben, müsste er vollständig neu spezifiziert werden.
Marko Topolnik
11

Gute Frage. Wie immer sollten wir zur Quelle gehen , um die Antwort zu finden ( "The Java® Virtual Machine Specification" ). Der Abschnitt erwähnt zwar nicht explizit ein Limit (wie auch die Java6-VM-Spezifikation), aber etwas umsichtig:

Die größte Anzahl lokaler Variablen im Array lokaler Variablen eines Frames, der beim Aufruf einer Methode erstellt wurde (§2.6), ist durch die Größe des Elements max_locals des Code-Attributs (§4.7.3), das den Code des Codes angibt, auf 65535 begrenzt Methode und durch die 16-Bit-Indizierung lokaler Variablen des Befehlssatzes der Java Virtual Machine.

Prost,

Anders R. Bystrup
quelle
5
Die "größte Anzahl lokaler Variablen" hat zufällig den gleichen numerischen Wert, ist aber immer noch eine ganz andere Sache als die "maximale Größe einer Methode", nach der das OP gefragt hat.
Holger
8

Es hat sich nicht geändert. Das Limit des Codes in Methoden beträgt sowohl in Java 7 als auch in Java 8 immer noch 64 KB.

Verweise:

  1. Aus der Java 7 Virtual Machine-Spezifikation ( 4.9.1 Static Constraints ):

Die statischen Einschränkungen für den Java Virtual Machine-Code in einer Klassendatei geben an, wie Java Virtual Machine-Anweisungen im Code-Array angeordnet werden müssen und wie die Operanden der einzelnen Anweisungen lauten müssen.

Die statischen Einschränkungen für die Anweisungen im Code-Array lauten wie folgt:

  • Das Code-Array darf nicht leer sein, daher darf das Element code_length nicht den Wert 0 haben.
  • Der Wert des Elements code_length muss kleiner als 65536 sein.
  1. Aus der Java 8 Virtual Machine-Spezifikation ( 4.7.3 Das Codeattribut ):

Der Wert des Elements code_length gibt die Anzahl der Bytes im Code-Array für diese Methode an.

Der Wert von code_length muss größer als Null (da das Code-Array nicht leer sein darf) und kleiner als 65536 sein.

Philipp Claßen
quelle
1

Andremoniy hat den java 7Teil dieser Frage bereits beantwortet , aber zu diesem Zeitpunkt schien es bald zu entscheiden, java 8also vervollständige ich die Antwort, um diesen Teil abzudecken:

Zitat aus jvms :

Die Tatsache, dass end_pc exklusiv ist, ist ein historischer Fehler im Design der Java Virtual Machine: Wenn der Java Virtual Machine-Code für eine Methode genau 65535 Byte lang ist und mit einer Anweisung endet, die 1 Byte lang ist, kann diese Anweisung nicht geschützt werden von einem Ausnahmebehandler. Ein Compiler-Writer kann diesen Fehler umgehen, indem er die maximale Größe des generierten Java Virtual Machine-Codes für eine Methode, eine Instanzinitialisierungsmethode oder einen statischen Initialisierer (die Größe eines beliebigen Code-Arrays) auf 65534 Byte begrenzt.

Wie Sie sehen, scheint dieses historische Problem zumindest in dieser Version (Java 8) keine Lösung zu finden.

mok
quelle
-1

Als Abhilfe kann und wenn Sie den Zugriff auf den Code des Parsers haben, können Sie es zur Arbeit in was auch immer ‚Grenzen ändern von den JVM - Compiler auferlegt werden ... (vorausgesetzt , es ewig dauern den't die Teile in dem Parser - Code zu finden , um ändern)

Ombud
quelle