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ć?


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

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.


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.


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?


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

2

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


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


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 ...


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ął.


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.


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ś.


0

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


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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.