Błąd kompilacji „Kod za duży” w Javie

94

Czy istnieje maksymalny rozmiar kodu w Javie? Napisałem funkcję z ponad 10 000 wierszami. Właściwie każdy wiersz przypisuje wartość do zmiennej tablicowej.

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"; 

A podczas kompilacji pojawia się ten błąd: kod jest za duży

Jak mam to przezwyciężyć?

trójca
źródło
9
Jestem oszołomiony ... Musi być lepszy sposób na zrobienie tego.
Thanos Papathanasiou
7
Naprawdę musisz spojrzeć na bazę danych pod kątem tego typu rzeczy, bez pliku właściwości.
Paul Whelan,
45
Dlaczego krzyczycie na biedaka za zły projekt? Może OP uzyskał tę szaloną metodę za pomocą jakiegoś narzędzia do generowania kodu.
webuster
15
Jestem oszołomiony, że te płytkie krytyczne komentarze otrzymały tak wiele pozytywnych głosów!
Evgeni Sergeev
7
Dlaczego uruchamianie aplikacji spędza dużo czasu na analizowaniu jakiegoś pliku tekstowego, skoro kompilator może wstępnie wygenerować wszystko w czasie kompilacji? To zły projekt, jeśli chcesz zmienić dane bez ponownej kompilacji lub napisać metodę ręcznie, ale nie jest to wcale zły projekt, jeśli generujesz kod źródłowy. (Przynajmniej jeśli zrobisz to w sposób, który faktycznie pozwala kompilatorowi na wstępne wygenerowanie tablicy).
Guntram Blohm

Odpowiedzi:

93

Pojedyncza metoda w klasie Java może mieć maksymalnie 64 KB kodu bajtowego.

Ale powinieneś to posprzątać!

Użyj .propertiespliku do przechowywania tych danych i załaduj je za pośrednictwemjava.util.Properties

Możesz to zrobić, umieszczając .propertiesplik w swojej ścieżce klas i używając:

Properties properties = new Properties();
InputStream inputStream = getClass().getResourceAsStream("yourfile.properties");
properties.load(inputStream);
Bozho
źródło
2
„Nieważne, jaki jest rzeczywisty rozmiar Twojego JDK / JVM”? Sugerujesz, że ten limit nie jest ustalony? Ponieważ jest to ustalone i wymagane przez specyfikację formatu pliku klasy.
Joachim Sauer
1
gdzie mogę znaleźć plik .properties
trinity
1
tworzysz własny, a następnie umieszczasz go na ścieżce klas
Mark
3
Nie skorzystałem z twojej sugestii, chociaż z chęcią spróbuję następnym razem .. użyłem bazy danych do przechowywania tych informacji i odpowiednio zmodyfikowałem resztę kodu.
trinity
1
Przepraszam, jeśli to głupie pytanie, ale… Gdzie należy umieścić ten plik .properties? To znaczy ok, to jest w ścieżce klas, ale gdzie to jest?
Milack27,
14

W metodzie istnieje ograniczenie rozmiaru kodu bajtowego do 64 KB

Powiedziawszy to, muszę się zgodzić z Richardem; dlaczego potrzebujesz tak dużej metody? Biorąc pod uwagę przykład w OP, plik właściwości powinien wystarczyć ... lub nawet baza danych, jeśli jest to wymagane.

Wszyscy
źródło
4
a co z wyliczeniami? mam ten sam problem z dużymi zestawami wyliczeń
Toby
1
@Toby: Nigdy nie spotkałem się z tym problemem w przypadku enum. Istnieją jednak posty innych użytkowników w SO na ten sam problem. Na przykład - stackoverflow.com/questions/2546470 Warto zajrzeć do wygenerowanego pliku .class i enumzobaczyć
Wszyscy
Instancje wyliczenia (tj. Obiekty reprezentujące stałe) są tworzone w statycznym inicjatorze klasy, który jest metodą i ma takie same ograniczenia.
czerwiec
Napotkałem ten sam problem z kodem generowanym przez framework dla naprawdę złożonego formularza internetowego. Rozwiązaniem było podzielenie formularza na komponenty, więc wygenerowany kod dla każdego komponentu również został podzielony.
SebaGra
13

Zgodnie ze specyfikacją Java Virtual Machine , kod metody nie może być większy niż 65536 bajtów :

Wartość code_lengthelementu określa liczbę bajtów w codetablicy dla tej metody.

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

code_lengthdefiniuje rozmiar code[]atrybutu, który zawiera rzeczywisty kod bajtowy metody:

codeTablica daje rzeczywiste bajtów kodu Java Virtual Machine, które implementują metody.

Joachim Sauer
źródło
7

To trochę przypomina szaleństwo. Czy nie możesz zainicjować tablicy, odczytując wartości z pliku tekstowego lub innego źródła danych?

RichardOD
źródło
3
(Negocjowane, ponieważ) To wymaga przynajmniej jednego powodu, dla którego taka technika jest zła. Nie jest łatwo wymyślić dobry powód.
Evgeni Sergeev
3

Ten błąd czasami występuje z powodu zbyt dużego kodu w jednej funkcji ... Aby rozwiązać ten błąd, podziel tę funkcję na wiele funkcji, takich jak

//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();
}
DevLoverUmar
źródło
2

Spróbuj refaktoryzować swój kod. W Javie istnieje ograniczenie rozmiaru metody.

Padmarag
źródło
1
refaktoryzacja nie wydaje się rozsądnym pomysłem, jeśli wszystko, co robi w tej metodzie, to inicjalizacja tablicy.
Gabriel Ščerbák
2
Powiedział, że reszta jego kodu zależy od tego, czy jest to tablica. Mógłby więc refaktoryzować metodę, aby przekazać odpowiedzialność za ładowanie danych do innej metody / fabryki z pliku / bazy danych.
Padmarag
możesz tworzyć i inicjować duże tablice bez uciekania się do tego rodzaju bzdur; zobacz odpowiedź @ Kris.
Stephen C,
Refaktoryzacja - „Proces zmiany kodu źródłowego programu komputerowego bez modyfikowania jego zewnętrznego zachowania funkcjonalnego w celu ulepszenia niektórych niefunkcjonalnych atrybutów oprogramowania”. Czym inne odpowiedzi różnią się od tego?
Padmarag
2

Jak wspomniano w innych odpowiedziach, istnieje limit 64 KB kodu bajtowego dla metody (przynajmniej w kompilatorze java firmy Sun)

Dla mnie sensowniejsze byłoby podzielenie tej metody na więcej metod - każda przypisuje pewne powiązane elementy do tablicy (może być bardziej sensowne użycie ArrayList w tym celu)

na przykład:

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

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

Alternatywnie możesz załadować elementy z zasobu statycznego, jeśli są one naprawione jak z pliku właściwości

saret
źródło
Prawidłowa odpowiedź to traktowanie danych jako danych, a kodu jako kodu.
Malcolm,
@Malcolm Cóż, to wyraźnie dane, a nie kod. Twój komentarz jest mylący, ponieważ nie powinieneś mieszać danych i kodu, ale tutaj nie są one mieszane.
Evgeni Sergeev
Myślę, że to dobre obejście. Przychodzę na ten problem z około 21 tysiącami linii kodu z 7000 wiadomościami tras. Naprawiam to, dzieląc te komunikaty tras na 7 funkcji o nazwie xxx0 xxx1 xxx2.
człowiek z brązu
2

Sam napotkałem ten problem. Rozwiązaniem, które zadziałało dla mnie, była refaktoryzacja i zmniejszenie metody do łatwiejszych w zarządzaniu fragmentów. Podobnie jak ty, mam do czynienia z metodą prawie 10 tys. Linii. Jednak dzięki zastosowaniu zmiennych statycznych, a także mniejszych funkcji modułowych, problem został rozwiązany.

Wydaje się, że byłoby lepsze obejście, ale w Javie 8 nie ma ...

Azadi B.
źródło
1

Możesz dodać inną metodę, aby utworzyć miejsce na kod dla dodatkowej przestrzeni danych, możesz mieć metodę, która zajmuje dużą ilość miejsca na dane. Spróbuj podzielić swoje metody, ponieważ miałem ten sam problem i napraw go, tworząc kolejną dodatkową metodę dla tych samych danych w moim kodzie java na Androida. Po tym, jak to zrobiłem, problem zniknął.

FermDroi
źródło
To bardziej komentarz niż odpowiedź.
user3071284
0

Mam wyliczenie, które powoduje, że rozmiar pliku .java przekracza 500 KB. Eclipse może go zbudować z jakiegoś powodu; plik build.xml wyeksportowany za pomocą eclipse nie może. Zaglądam do tego i zaktualizuję ten post.

Richard Jessop
źródło
0

Ponieważ istnieje limit rozmiaru dla metod i nie chcesz przeprojektowywać swojego kodu w tej chwili, możesz podzielić tablicę na 4-5 części, a następnie umieścić je w różnych metodach. W czasie czytania tablicy wywołaj wszystkie metody w serii. Możesz również utrzymywać licznik, aby wiedzieć, ile indeksów przeanalizowałeś.

Vikram Bhardwaj
źródło
0

jest to spowodowane całym kodem w rozwiązaniu pojedynczych metod: utwórz więcej małych metod, a ten błąd zniknie

jaigish
źródło
0

ok, może ta odpowiedź jest za późno, ale myślę, że ta droga jest lepsza niż inna

na przykład mamy 1000 wierszy danych w kodzie

  1. rozgryść ich

    private void rows500() {
         //you shoud write 1-500 rows here
    }
    
    private void rows1000() {
         you shoud write 500-1000 rows here
    }
    
  2. aby uzyskać lepszą wydajność, umieść w swoich kodach „jeśli”

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

Mam nadzieję, że ten kod ci pomoże

RahimpoorDeveloper
źródło