Ошибка компиляции «Код слишком большой» в Java


94

Есть ли максимальный размер кода на Java? Я написал функцию с более чем 10 000 строками. Фактически, каждая строка присваивает значение переменной массива.

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
Я просто ошеломлен ... Наверное, будет лучший способ сделать это.
Танос Папатанасиу,

7
Вам действительно нужно просмотреть базу данных для такого рода вещей, если это не файл свойств.
Пол Уилан,

45
Почему вы кричите на беднягу за плохой дизайн? Возможно, OP получил этот безумный метод с помощью какого-то инструмента для генерации кода.
webuster 09

15
Я ошеломлен тем, что эти неглубокие критические комментарии получили столько голосов!
Евгений Сергеев

7
Почему запуск вашего приложения тратит много времени на синтаксический анализ какого-то текстового файла, когда вы можете заставить компилятор предварительно сгенерировать все во время компиляции? Это плохой дизайн, если вы хотите изменить данные без перекомпиляции или написать метод вручную, но это совсем не плохой дизайн, если вы создаете исходный код. (По крайней мере, если вы делаете это так, чтобы компилятор мог предварительно сгенерировать массив).
Guntram Blohm

Ответы:


93

Байт-код одного метода в классе Java может составлять не более 64 КБ.

Но вы должны это очистить!

Используйте .propertiesфайл для хранения этих данных и загрузите его черезjava.util.Properties

Вы можете сделать это, поместив .propertiesфайл в свой путь к классам и используя:

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

2
«Независимо от фактического размера вашего JDK / JVM»? Вы хотите сказать, что этот лимит не установлен? Потому что это фиксировано и требуется спецификацией формата файла класса.
Joachim Sauer

1
где я могу найти файл .properties
троица

1
вы создаете свой собственный, а затем помещаете его в путь к классам
Марк,

3
Я не использовал ваше предложение, хотя мне не терпится попробовать его в следующий раз ... теперь я использовал базу данных для хранения этой информации и соответствующим образом изменил остальную часть кода ...
trinity

1
Прошу прощения, если это глупый вопрос, но ... Куда положить этот файл .properties? Я имею в виду, хорошо, это в пути к классам, но где это?
Milack27,

14

Для метода существует ограничение на размер байтового кода 64 КБ.

Сказав это, я должен согласиться с Ричардом; зачем вам такой большой метод? Учитывая пример в OP, файла свойств должно хватить ... или даже базы данных, если требуется.


4
как насчет перечислений? у меня такая же проблема с большими наборами перечислений
Тоби

1
@Toby: Я никогда не сталкивался с этой проблемой с enum. Тем не менее, здесь на SO есть сообщения других пользователей по той же проблеме. Например - stackoverflow.com/questions/2546470 Возможно, стоит заглянуть в сгенерированный файл .class, enumчтобы увидеть
Всем

Экземпляры Enum (т.е. объекты, представляющие константы) создаются в статическом инициализаторе класса, который является методом и имеет такое же ограничение.
juancn

Я столкнулся с той же проблемой с кодом, созданным фреймворком для действительно сложной веб-формы. Решением было разделить форму на компоненты, поэтому сгенерированный код для каждого компонента также был разделен.
SebaGra

13

Согласно спецификации виртуальной машины Java , код метода не должен превышать 65536 байт :

Значение code_lengthэлемента дает количество байтов в codeмассиве для этого метода.

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

code_lengthопределяет размер code[]атрибута, который содержит фактический байт-код метода:

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


7

Это немного похоже на безумие. Можете ли вы инициализировать массив, прочитав значения из текстового файла или другого источника данных?


3
(Проголосовано против, потому что) Требуется хотя бы одна причина, по которой такая техника плохая. Придумать вескую причину непросто.
Евгений Сергеев

3

Эта ошибка иногда возникает из-за слишком большого кода в одной функции ... Чтобы решить эту ошибку, разделите эту функцию на несколько функций, например

//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();
}

2

Попробуйте реорганизовать свой код. В Java есть ограничение на размер метода.


1
рефакторинг не кажется разумной идеей, если все, что он делает в этом методе, - это инициализация массива.
Габриэль Щербак,

2
Он сказал, что остальная часть его кода зависит от того, что это массив. Таким образом, он мог реорганизовать метод, чтобы передать ответственность за загрузку данных другому методу / фабрике из файла / базы данных.
Padmarag

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

Рефакторинг - «Процесс изменения исходного кода компьютерной программы без изменения ее внешнего функционального поведения с целью улучшения некоторых нефункциональных атрибутов программного обеспечения». Чем другие ответы отличаются от этого?
Padmarag

2

Как упоминалось в других ответах, для метода существует ограничение на 64 КБ байт-кода (по крайней мере, в Java-компиляторе Sun)

Тоже мне было бы разумнее разбить этот метод на несколько методов - каждый из которых назначает определенные связанные вещи в массив (может иметь больше смысла использовать для этого ArrayList)

например:

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

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

В качестве альтернативы вы можете загружать элементы из статического ресурса, если они исправлены, как из файла свойств.


Правильный ответ - рассматривать данные как данные, а код как код.
Малькольм

@Malcolm Ну, это явно данные, а не код. Ваш комментарий вводит в заблуждение, потому что вам не следует смешивать данные и код, но здесь они не смешиваются.
Евгений Сергеев

Я думаю, что это хорошая работа. Я столкнулся с этой проблемой примерно с 21k строками кода с 7000 маршрутными сообщениями в нем. Я исправил это, разделив эти маршрутные сообщения на 7 функций с именем xxx0 xxx1 xxx2.
бронзовый мужчина

2

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

Кажется, было бы лучшее решение, но с использованием Java 8 его нет ...


1

Вы можете добавить другой метод, чтобы освободить место для вашего кода для дополнительного пространства данных, у вас может быть метод, который занимает большой объем пространства данных. Попробуйте разделить свои методы, потому что у меня была такая же проблема, и исправьте ее, создав еще один дополнительный метод для тех же данных в моем Java-коде Android. Проблема исчезла после того, как я это сделал.


Это больше комментарий, чем ответ.
user3071284

0

У меня есть перечисление, из-за которого размер файла .java превышает 500 КБ. Eclipse может его построить по какой-то причине; экспортированный из eclipse файл ant 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.