Maksymalny rozmiar metody w Javie 7 i 8

82

Wiem, że metoda w Javie nie może być większa niż 64 KB. Ograniczenie powoduje problemy z generowanym kodem z gramatyki JavaCC . Mieliśmy problemy z Javą 6 i mogliśmy to naprawić, zmieniając gramatykę. Czy limit został zmieniony dla Java 7, czy jest planowany dla Java 8?

Żeby to było jasne. Nie potrzebuję samodzielnie metody większej niż 64 KB. Ale napisałem gramatykę, która składa się z bardzo dużej metody.

LaurentG
źródło
4
Napotkałem ten sam problem, gdy próbowałem skompilować ogromny kod brainf ** k.
johnchen902
3
Biorąc pod uwagę brak informacji, że jest inaczej, myślę, że można bezpiecznie założyć, że ten limit będzie nadal egzekwowany w Javie 8 ... Oczywiście inną (kosztowną) opcją może być zmiana silnika gramatyki na parboiled , co pozwala na napisz gramatykę w czystej Javie.
fge
4
spójrz na ten artykuł
Anirudha
7
Osobiście uważam, że tworzenie tak dużych metod jest błędem w JavaCC . Naprawdę powinien być w stanie rozpowszechniać swój kod. Zwłaszcza biorąc pod uwagę, że JVM zdecydowanie nie jest zbudowany do optymalizacji tak ogromnych metod.
Joachim Sauer

Odpowiedzi:

58

Według JVMS7 :

Fakt, że funkcja end_pc jest wyłączna, jest historycznym błędem w projektowaniu wirtualnej maszyny Javy: jeśli kod maszyny wirtualnej Javy dla metody ma długość dokładnie 65535 bajtów i kończy się instrukcją o długości 1 bajtu, wówczas ta instrukcja nie może być chroniona przez program obsługi wyjątków. Program zapisujący kompilator może obejść ten błąd, ograniczając maksymalny rozmiar generowanego kodu maszyny wirtualnej Java dla dowolnej metody, metody inicjowania instancji lub inicjatora statycznego (rozmiar dowolnej tablicy kodu) do 65534 bajtów.

Ale o to chodzi Java 7. Nie ma ostatecznej specyfikacji Java 8, więc nikt (poza jej twórcami) nie mógł odpowiedzieć na to pytanie.

UPD (2015-04-06) Według JVM8 dotyczy to również Java 8.

Andremoniy
źródło
2
Naprawdę jest taki „błąd” w Javie, którego wciąż nie naprawiono? Może to być poważne ograniczenie, szczególnie w przypadku LaurentG.
Francesco Belladonna
3
@ Fire-Dragon-DoL Cytowana dyskusja dotyczy tylko metody, która musi być o jeden bajt krótsza niż mogłaby być w innym przypadku. To zupełnie nieistotne. Ograniczenie to nie wynika z żadnego prostego „błędu”, takiego jak ten: występuje w ogólnym projekcie kodu bajtowego i naprawienie go wymagałoby ponownego określenia go w całości.
Marko Topolnik
11

Dobre pytanie. Jak zawsze powinniśmy udać się do źródła, aby znaleźć odpowiedź ( „Specyfikacja maszyny wirtualnej Java®” ). Sekcja nie wspomina jednak wyraźnie o limicie (tak jak w specyfikacji maszyny wirtualnej Java6), ale dość ostrożnie:

Największa liczba zmiennych lokalnych w tablicy zmiennych lokalnych ramki utworzonej po wywołaniu metody (§2.6) jest ograniczona do 65535 przez wielkość pozycji max_locals atrybutu Code (§4.7.3) podającej kod oraz przez 16-bitowe indeksowanie zmiennych lokalnych zestawu instrukcji wirtualnej maszyny języka Java.

Twoje zdrowie,

Anders R. Bystrup
źródło
5
„Największa liczba zmiennych lokalnych” ma taką samą wartość liczbową, ale wciąż jest czymś zupełnie innym niż „maksymalny rozmiar metody”, o który prosił PO.
Holger,
8

To się nie zmieniło. Limit kodu w metodach nadal wynosi 64 KB zarówno w języku Java 7, jak i Java 8.

Bibliografia:

  1. Ze specyfikacji maszyny wirtualnej Java 7 ( 4.9.1 statyczne ograniczenia ):

Statyczne ograniczenia kodu wirtualnej maszyny języka Java w pliku klasy określają, w jaki sposób instrukcje wirtualnej maszyny języka Java muszą być ułożone w tablicy kodu i jakie muszą być operandy poszczególnych instrukcji.

Statyczne ograniczenia instrukcji w tablicy kodu są następujące:

  • Tablica kodu nie może być pusta, więc element długość_kodu nie może mieć wartości 0.
  • Wartość pozycji code_length musi być mniejsza niż 65536.
  1. Ze specyfikacji maszyny wirtualnej Java 8 ( 4.7.3 atrybut kodu ):

Wartość elementu code_length określa liczbę bajtów w tablicy kodu dla tej metody.

Wartość code_length musi być większa od zera (ponieważ tablica code nie może być pusta) i mniejsza niż 65536.

Philipp Claßen
źródło
1

Andremoniy już odpowiedział na java 7część tego pytania, ale wydaje się, że w tamtym czasie należało zadecydować, java 8więc uzupełniam odpowiedź, aby opisać tę część:

Cytowanie z jvms :

Fakt, że parametr end_pc jest wyłączny, jest historycznym błędem w projektowaniu wirtualnej maszyny Javy: jeśli kod wirtualnej maszyny języka Java dla metody ma długość dokładnie 65535 bajtów i kończy się instrukcją o długości 1 bajtu, wówczas ta instrukcja nie może być chroniona przez program obsługi wyjątków. Program zapisujący kompilator może obejść ten błąd, ograniczając maksymalny rozmiar generowanego kodu maszyny wirtualnej Java dla dowolnej metody, metody inicjowania instancji lub inicjatora statycznego (rozmiar dowolnej tablicy kodu) do 65534 bajtów.

Jak widać, ten historyczny problem nie wydaje się rozwiązać przynajmniej w tej wersji (java 8).

mok
źródło
-1

Aby obejść ten problem, jeśli masz dostęp do kodu parsera, możesz zmodyfikować go tak, aby działał w ramach jakichkolwiek ograniczeń nałożonych przez kompilator JVM ... (Zakładając, że znalezienie fragmentów kodu parsera nie zajmie wieczności modyfikować)

ombud
źródło