Помилка компіляції "Код занадто великий" у Java


94

Чи існує якийсь максимальний розмір коду в Java? Я написав функцію з понад 10000 рядків. Власне, кожен рядок присвоює значення змінної масиву.

arts_bag[10792]="newyorkartworld";
arts_bag[10793]="leningradschool";
arts_bag[10794]="mailart";
arts_bag[10795]="artspan";
arts_bag[10796]="watercolor";
arts_bag[10797]="sculptures";
arts_bag[10798]="stonesculpture"; 

І під час компіляції я отримую таку помилку: код занадто великий

Як мені це подолати?


9
Я просто приголомшений ... Для цього обов’язково буде кращий спосіб.
Танос Папатанасіу

6
Вам дійсно потрібно переглянути базу даних для цього типу речей, не вдавшись до файлу властивостей.
Paul Whelan,

44
Чому ви, хлопці, кричите на бідолаху за поганий дизайн? Можливо, OP отримав цей божевільний метод за допомогою якогось інструменту генерації коду.
webuster

14
Я приголомшений тим, що ці неглибокі критичні коментарі набрали стільки голосів!
Євген Сергєєв

7
Чому запуск програми витрачає багато часу на синтаксичний аналіз якогось текстового файлу, коли компілятор може попередньо генерувати все під час компіляції? Це поганий дизайн, якщо ви хочете змінити дані без перекомпіляції або написати метод вручну, але це зовсім не поганий дизайн, якщо ви створюєте вихідний код. (Принаймні, якщо ви робите це таким чином, що насправді дозволяє компілятору попередньо генерувати масив).
Guntram Blohm підтримує Моніку

Відповіді:


92

Один метод у класі Java може містити не більше 64 КБ байт-коду.

Але вам слід прибрати це!

Використовуйте .propertiesфайл для зберігання цих даних та завантаження черезjava.util.Properties

Ви можете зробити це, розмістивши .propertiesфайл у своєму шляху до класу та скориставшись:

Properties properties = new Properties();
InputStream inputStream = getClass().getResourceAsStream("yourfile.properties");
properties.load(inputStream);

2
"Незалежно від фактичного розміру вашого JDK / JVM"? Ви натякаєте, що ця межа не фіксована? Оскільки це виправлено та вимагається специфікацією формату файлу класу.
Йоахім Зауер

1
де я можу знайти файл .properties
трійця,

1
ви створюєте свій власний, а потім ставите його на шлях до уроків
Марк

3
я не використав вашу пропозицію, хоча я хочу спробувати її наступного разу .. зараз використовував базу даних для зберігання цієї інформації і відповідно змінив решту коду ..
Трійця,

1
Вибачте, якщо це дурне запитання, але .. Куди слід додати цей файл .properties? Я маю на увазі, добре, це в класі, але де воно?
Milack27,

14

Для методу встановлено обмеження у розмірі 64 байт-коду

Сказавши це, я повинен погодитися з Річардом; навіщо потрібен такий великий метод? Враховуючи приклад в OP, вистачить файлу властивостей ... або навіть бази даних, якщо потрібно.


4
як щодо переліків? я отримую те саме випуск із великими наборами переліків
Тобі

1
@Toby: Я сам ніколи не стикався з цією проблемою. Є публікації інших користувачів тут на SO про те саме питання. Наприклад - stackoverflow.com/questions/2546470 Можливо, варто заглянути у згенерований файл .class, enumщоб побачити
кожному,

Екземпляри Enum (тобто об'єкти, що представляють константи) створюються в статичному ініціалізаторі класу, який є методом і має однакові обмеження.
juancn

Я зіткнувся з тією ж проблемою з кодом, сформованим у рамках для дуже складної веб-форми. Рішенням було розділити форму на компоненти, тому згенерований код для кожного компонента також був розділений.
SebaGra,

12

Відповідно до специфікації віртуальної машини Java , код методу не повинен перевищувати 65536 байт :

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

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

code_lengthвизначає розмір code[]атрибута, який містить фактичний байт-код методу:

codeМасив дає фактичні байт коду Java Virtual Machine, що реалізують метод.


7

Це здається трохи схожим на божевілля. Чи не можете ви ініціалізувати масив, прочитавши значення з текстового файлу чи іншого джерела даних?


3
(Проголосовано проти). Для цього потрібна принаймні одна причина, чому така техніка є поганою. Неважко придумати поважну причину.
Євген Сергєєв

2

Спробуйте переформатувати свій код. Розмір методу в Java обмежений.


1
рефакторинг не здається розумною ідеєю, якщо все, що він робить у цьому методі, - це ініціалізація масиву.
Габріель Шчербак

2
Він сказав, що решта його коду залежить від того, що це масив. Тож він міг рефакторизувати метод, щоб передати відповідальність за завантаження даних якомусь іншому методу / фабриці з файлу / бази даних.
Падмараг

ви можете створювати та ініціалізувати великі масиви, не вдаючись до подібних дурниць; див. відповідь @ Kris.
Stephen C

Рефактор - «Процес зміни вихідного коду комп’ютерної програми без зміни її зовнішньої функціональної поведінки з метою покращення деяких нефункціональних атрибутів програмного забезпечення». Чим інші відповіді відрізняються від цього?
Падмараг,

2

Як згадувалося в інших відповідях, для методу існує обмеження в 64 КБ (принаймні, у Java-компіляторі Sun)

Для мене також було б більш розумно розбити цей метод на більше методів - кожен призначити певні пов’язані речі масиву (може мати більше сенсу використовувати ArrayList для цього)

наприклад:

public void addArrayItems()
{
  addSculptureItems(list);
  ...
}

public void addSculptureItems(ArrayList list)
{
  list.add("sculptures");
  list.add("stonesculpture");
}

Крім того, ви можете завантажити елементи зі статичного ресурсу, якщо вони виправлені як у файлі властивостей


Правильна відповідь - трактувати дані як дані, а код як код.
Малкольм

@Malcolm Ну, це явно дані, а не код. Ваш коментар вводить в оману, оскільки те, що ви не повинні робити, - це змішувати дані та код, але тут вони не змішуються.
Євген Сергєєв

Я вважаю, що це хороша робота. Я стикаюся з цією проблемою з приблизно 21 тис. Рядків коду з 7000 повідомленнями маршрутів. Я виправляю це шляхом поділу цих повідомлень маршруту на функцію 7 з ім'ям xxx0 xxx1 xxx2.
бронзова людина

2

Я сам зіткнувся з цією проблемою. Рішення, яке працювало для мене, полягало в переробці та зменшенні методу на більш керовані частини. Як і ви, я маю справу з методом лінії майже 10 тис. Однак із використанням статичних змінних, а також менших модульних функцій, проблема була вирішена.

Здається, було б кращого обхідного шляху, але, використовуючи Java 8, його немає ...


2

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

//Too large code function
private void mySingleFunction(){
.
.
2000 lines of code
}
//To solve the problem
private void mySingleFunction_1(){
.
.
500 lines of code
}
private void mySingleFunction_2(){
.
.
500 lines of code
}
private void mySingleFunction_3(){
.
.
500 lines of code
}
private void mySingleFunction_4(){
.
.
500 lines of code
}
private void MySingleFunction(){
mySingleFunction_1();
mySingleFunction_2();
mySingleFunction_3();
mySingleFunction_4();
}

1

Ви можете додати інший метод, щоб створити місце для коду для додаткового простору даних, можливо, у вас є метод, який займає велику кількість простору даних. Спробуйте розділити свої методи, тому що у мене була та сама проблема, і виправте її, створивши ще один додатковий метод для тих самих даних у моєму коді java Android. Проблема зникла після того, як я це зробив.


Це більше коментар, ніж відповідь.
user3071284

0

У мене є перелік, через який файл .java перевищує 500 КБ. Eclipse може його побудувати з якихось причин; експортований затемненням мураха build.xml не може. Я розглядаю це і оновлю цю публікацію.


0

Оскільки для методів існує обмеження розміру, і ви не хочете переробляти свій код на даний момент, можливо, ви можете розділити масив на 4-5 частин, а потім помістити їх у різні методи. Під час читання масиву викличте всі методи послідовно. Ви можете також підтримувати лічильник, щоб знати, скільки індексів ви проаналізували.


0

це пов’язано з усім кодом в одному методі рішення: створіть більше невеликих методів, тоді ця помилка зникне


0

добре, можливо, ця відповідь запізно, але я думаю, що цей шлях кращий, ніж інший спосіб

наприклад, у нас є 1000 рядків даних у коді

  1. зламати їх

    private void rows500() {
         //you shoud write 1-500 rows here
    }
    
    private void rows1000() {
         you shoud write 500-1000 rows here
    }
  2. для кращої продуктивності поставте "якщо" у ваші коди

    if (count < 500) {
        rows500();
    } else if (count > 500) {
        rows1000();
    }

Сподіваюся, цей код вам допоможе

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