Максимальний розмір методу в Java 7 і 8


82

Я знаю, що метод не може перевищувати 64 КБ з Java. Обмеження викликає проблеми з генерованим кодом із граматики JavaCC . У нас були проблеми з Java 6, і ми змогли це виправити, змінивши граматику. Чи було змінено обмеження для Java 7 чи воно планується для Java 8?

Тільки щоб це було зрозуміло. Мені не потрібен метод розміром більше 64 КБ. Але я написав граматику, яка складається дуже великим методом.


4
З тією ж проблемою я зіткнувся, коли намагався скомпонувати величезний код brainf ** k.
johnchen902

3
Враховуючи відсутність інформації про протилежне, я думаю, можна з упевненістю припустити, що ця межа все ще буде застосовуватися в Java 8 ... Звичайно, ще одним (дорогим) варіантом може бути зміна механізму граматики на пропарений , що дозволяє вам пишіть свої граматики на чистій Java.
fge

4
погляньте на цю статтю
Анірудха

7
Особисто я думаю, що створення таких великих методів є помилкою в JavaCC . Він справді повинен мати можливість поширювати свій код. Особливо враховуючи, що JVM точно не створений для оптимізації таких величезних методів.
Йоахім Зауер

Відповіді:


58

Відповідно до JVMS7 :

Той факт, що end_pc є ексклюзивним, є історичною помилкою у розробці віртуальної машини Java: якщо код віртуальної машини Java для методу має рівно 65535 байт і закінчується інструкцією довжиною в 1 байт, то ця інструкція не може бути захищена обробником винятків. Записник компілятора може обійти цю помилку, обмеживши максимальний розмір згенерованого коду віртуальної машини Java для будь-якого методу, методу ініціалізації екземпляра або статичного ініціалізатора (розмір будь-якого масиву коду) до 65534 байт.

Але це приблизно Java 7. Останні специфікації для Java 8 відсутні, тому ніхто (крім розробників) не може відповісти на це питання.

UPD (06.04.2015) Відповідно до JVM8 це також стосується Java 8.


2
Невже в Java є така "помилка", що вона все ще не виправлена? Це може бути важким обмеженням, особливо для ситуації з LaurentG.
Франческо Беладонна

3
@ Fire-Dragon-DoL Наведена дискусія стосується лише методу, який повинен бути на один байт меншим за довжиною, ніж це могло б бути інакше. Це зовсім несуттєво. Обмеження не пов'язане з якоюсь простою "помилкою", подібною до цієї: це в загальному дизайні байт-коду, і для його виправлення знадобиться його повна відповідність.
Marko Topolnik

11

Гарне питання. Як завжди , ми повинні йти до джерела , щоб знайти відповідь ( «Java® специфікації віртуальної машини» ). У цьому розділі явно не згадується обмеження (як це було зроблено у специфікації Java6 VM), але дещо обережно:

Найбільша кількість локальних змінних у масиві локальних змінних кадру, створеного при виклику методу (§2.6), обмежується 65535 розміром елемента max_locals атрибута Code (§4.7.3), що дає код методом та за допомогою 16-бітової індексації локальної змінної набору інструкцій віртуальної машини Java.

Ура,


5
“Найбільша кількість локальних змінних” має однакові числові значення, але все ще є абсолютно іншою річчю, ніж “максимальний розмір методу”, просив ОП.
Holger

8

Це не змінилося. Обмеження коду в методах як і раніше залишається 64 КБ як в Java 7, так і в Java 8.

Список літератури:

  1. З специфікації віртуальної машини Java 7 ( 4.9.1 Статичні обмеження ):

Статичні обмеження коду віртуальної машини Java у файлі класу вказують, як інструкції віртуальної машини Java повинні бути викладені в масиві коду та якими операндами повинні бути окремі інструкції.

Статичні обмеження для інструкцій у масиві коду такі:

  • Масив коду не повинен бути порожнім, тому елемент code_length не може мати значення 0.
  • Значення елемента code_length має бути менше 65536.
  1. З специфікації віртуальної машини Java 8 ( 4.7.3 Атрибут коду ):

Значення елемента code_length дає кількість байтів у масиві коду для цього методу.

Значення code_length має бути більше нуля (оскільки масив коду не повинен бути порожнім) і менше 65536.


1

Андремоній вже відповів на java 7частину цього запитання, але, схоже, на той час це скоро вирішили, java 8тому я закінчую відповідь, щоб висвітлити цю частину:

Посилання з jvms :

Той факт, що end_pc є ексклюзивним, є історичною помилкою у розробці віртуальної машини Java: якщо код віртуальної машини Java для методу має рівно 65535 байт і закінчується інструкцією довжиною в 1 байт, то ця інструкція не може бути захищена обробником винятків. Записник компілятора може обійти цю помилку, обмеживши максимальний розмір згенерованого коду віртуальної машини Java для будь-якого методу, методу ініціалізації екземпляра або статичного ініціалізатора (розмір будь-якого масиву коду) до 65534 байт.

Як бачите, здається, ця історична проблема, здається, не вирішує принаймні в цій версії (Java 8).


-1

Як обхідне рішення, і якщо у вас є доступ до коду синтаксичного аналізатора, ви можете змінити його так, щоб він працював у межах, обмежених компілятором JVM ... (Припускаючи, що не знадобиться вічно знаходити частини в коді парсера, щоб змінити)

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