Kompilierungsfehler "Code zu groß" in Java

94

Gibt es eine maximale Größe für Code in Java? Ich habe eine Funktion mit mehr als 10.000 Zeilen geschrieben. Tatsächlich weist jede Zeile einer Arrayvariablen einen Wert zu.

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

Und beim Kompilieren erhalte ich folgende Fehlermeldung: Code zu groß

Wie überwinde ich das?

Dreieinigkeit
quelle
9
Ich bin nur fassungslos ... Es gibt bestimmt einen besseren Weg, dies zu tun.
Thanos Papathanasiou
6
Sie müssen sich wirklich eine Datenbank für diese Art von Dingen ansehen, andernfalls eine Eigenschaftendatei.
Paul Whelan
44
Warum schreit ihr den armen Kerl wegen schlechten Designs an? Vielleicht hat OP diese verrückte Methode durch ein Codegenerierungswerkzeug erhalten.
Webuster
14
Ich bin fassungslos, dass diese oberflächlichen kritischen Kommentare so viele positive Stimmen bekommen haben!
Evgeni Sergeev
7
Warum hat Ihr Anwendungsstart viel Zeit damit verbracht, eine Textdatei zu analysieren, wenn der Compiler beim Kompilieren alles vorgenerieren kann? Dies ist ein schlechtes Design, wenn Sie die Daten ändern möchten, ohne sie neu zu kompilieren, oder die Methode manuell schreiben möchten, aber es ist überhaupt kein schlechtes Design, wenn Sie den Quellcode generieren. (Zumindest, wenn Sie dies so tun, dass der Compiler das Array tatsächlich vorgenerieren kann).
Guntram Blohm unterstützt Monica

Antworten:

91

Eine einzelne Methode in einer Java-Klasse kann höchstens 64 KB Bytecode enthalten.

Aber du solltest das aufräumen!

Verwenden Sie die .propertiesDatei, um diese Daten zu speichern und über zu ladenjava.util.Properties

Sie können dies tun, indem Sie die .propertiesDatei in Ihrem Klassenpfad platzieren und Folgendes verwenden:

Properties properties = new Properties();
InputStream inputStream = getClass().getResourceAsStream("yourfile.properties");
properties.load(inputStream);
Bozho
quelle
2
"Egal wie groß Ihr JDK / JVM tatsächlich ist"? Wollen Sie damit sagen, dass dieses Limit nicht festgelegt ist? Weil es in der Spezifikation des Klassendateiformats festgelegt und erforderlich ist.
Joachim Sauer
1
Wo finde ich die .properties-Datei
Trinity
1
Sie erstellen Ihre eigenen und legen sie dann auf den Klassenpfad
Mark
3
Ich habe Ihren Vorschlag nicht verwendet, obwohl ich ihn beim nächsten Mal unbedingt ausprobieren möchte. Ich habe jetzt eine Datenbank zum Speichern dieser Informationen verwendet und den Rest des Codes entsprechend geändert.
Trinity
1
Es tut mir leid, wenn dies eine dumme Frage ist, aber .. Wo soll diese .properties-Datei abgelegt werden? Ich meine, ok, es ist im Klassenpfad, aber wo ist es?
Milack27
14

Es gibt eine Größenbeschränkung von 64 KByte für eine Methode

Trotzdem muss ich Richard zustimmen; Warum brauchen Sie eine so große Methode? In Anbetracht des Beispiels im OP sollte eine Eigenschaftendatei ausreichen ... oder bei Bedarf sogar eine Datenbank.

Jeder
quelle
4
wie wäre es mit Aufzählungen? Ich bekomme das gleiche Problem mit großen Mengen von Aufzählungen
Toby
1
@Toby: Ich habe dieses Problem nie mit enum selbst konfrontiert. Es gibt jedoch Beiträge anderer Benutzer hier auf SO zu demselben Thema. Zum Beispiel - stackoverflow.com/questions/2546470 Es kann sich lohnen, in die generierte .class-Datei zu schauen, um enumzu sehen
Jeder
Enum-Instanzen (dh die Objekte, die die Konstanten darstellen) werden im statischen Initialisierer der Klasse erstellt, der eine Methode ist und dieselbe Einschränkung aufweist.
13.
Ich hatte das gleiche Problem mit vom Framework generiertem Code für ein wirklich komplexes Webformular. Die Lösung bestand darin, das Formular in Komponenten aufzuteilen, sodass der generierte Code für jede Komponente ebenfalls aufgeteilt wurde.
SebaGra
12

Gemäß der Java Virtual Machine Spezifikation , muss der Code einer Methode nicht größer als 65536 Bytes sein :

Der Wert des code_lengthElements gibt die Anzahl der Bytes im codeArray für diese Methode an.

Der Wert von code_length muss größer als Null (da das Code-Array nicht leer sein darf) und kleiner als 65536 sein.

code_lengthdefiniert die Größe des code[]Attributs, das den tatsächlichen Bytecode einer Methode enthält:

Das codeArray gibt die tatsächlichen Bytes des Java Virtual Machine-Codes an, die die Methode implementieren.

Joachim Sauer
quelle
7

Das scheint ein bisschen wie Wahnsinn. Können Sie das Array nicht durch Lesen der Werte aus einer Textdatei oder einer anderen Datenquelle initialisieren?

RichardOD
quelle
3
(Da herabgestuft, weil) Dies braucht mindestens einen Grund, warum eine solche Technik schlecht ist. Es ist nicht einfach, einen guten Grund zu finden.
Evgeni Sergeev
2

Versuchen Sie, Ihren Code umzugestalten. Die Größe der Methode in Java ist begrenzt.

Padmarag
quelle
1
Refactoring ist keine vernünftige Idee, wenn er bei dieser Methode nur die Array-Initialisierung durchführt.
Gabriel Ščerbák
2
Er sagte, dass der Rest seines Codes davon abhängt, dass es sich um ein Array handelt. So konnte er die Methode umgestalten, um die Verantwortung für das Laden von Daten aus einer Datei / Datenbank auf eine andere Methode / Factory zu übertragen.
Padmarag
Sie können große Arrays erstellen und initialisieren, ohne auf diese Art von Unsinn zurückzugreifen. siehe @ Kris Antwort.
Stephen C
Refactor - "Prozess zum Ändern des Quellcodes eines Computerprogramms, ohne dessen externes Funktionsverhalten zu ändern, um einige der nicht funktionalen Attribute der Software zu verbessern." Wie unterscheiden sich andere Antworten davon?
Padmarag
2

Wie in anderen Antworten erwähnt, gibt es für eine Methode ein Bytecode-Limit von 64 KB (zumindest im Java-Compiler von Sun).

Für mich wäre es sinnvoller, diese Methode in mehrere Methoden aufzuteilen - jede weist dem Array bestimmte verwandte Dinge zu (möglicherweise ist es sinnvoller, eine ArrayList zu verwenden, um dies zu tun).

beispielsweise:

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

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

Alternativ können Sie die Elemente aus einer statischen Ressource laden, wenn sie wie aus einer Eigenschaftendatei behoben sind

Saret
quelle
Die richtige Antwort besteht darin, Daten als Daten und Code als Code zu behandeln.
Malcolm
@ Malcolm Nun, das sind eindeutig Daten und kein Code. Ihr Kommentar ist irreführend, denn Sie sollten Daten und Code nicht mischen , aber hier werden sie nicht gemischt.
Evgeni Sergeev
Ich denke, dies ist eine gute Lösung. Ich stoße auf dieses Problem mit etwa 21.000 Codezeilen mit 7000 Routennachrichten. Ich behebe es, indem ich diese Routennachrichten in 7 Funktionen mit dem Namen xxx0 xxx1 xxx2 teile.
Bronzemann
2

Ich bin selbst auf dieses Problem gestoßen. Die Lösung, die für mich funktioniert hat, bestand darin, die Methode zu überarbeiten und auf handlichere Teile zu verkleinern. Wie Sie habe ich es mit einer fast 10K-Linienmethode zu tun. Mit der Verwendung statischer Variablen sowie kleinerer modularer Funktionen wurde das Problem jedoch gelöst.

Es scheint eine bessere Problemumgehung zu geben, aber mit Java 8 gibt es keine ...

Azadi B.
quelle
2

Dieser Fehler tritt manchmal aufgrund von zu großem Code in einer einzelnen Funktion auf ... Um diesen Fehler zu beheben, teilen Sie diese Funktion in mehrere Funktionen auf, z

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

Sie können eine weitere Methode hinzufügen, um Platz für Ihren Code für zusätzlichen Datenraum zu schaffen. Möglicherweise verfügen Sie über eine Methode, die viel Datenraum beansprucht. Versuchen Sie, Ihre Methoden zu teilen, da ich das gleiche Problem hatte, und beheben Sie es, indem Sie eine weitere zusätzliche Methode für die gleichen Daten in meinem Java-Android-Code erstellen. Das Problem war danach behoben.

FermDroi
quelle
Dies ist eher ein Kommentar als eine Antwort.
user3071284
0

Ich habe eine Aufzählung, die bewirkt, dass die Java-Datei über 500 KB groß ist. Eclipse kann es aus irgendeinem Grund bauen; Die von Eclipse exportierte Ameise build.xml kann nicht. Ich schaue mir das an und werde diesen Beitrag aktualisieren.

Richard Jessop
quelle
0

Da es eine Größenbeschränkung für Methoden gibt und Sie Ihren Code in diesem Moment nicht neu gestalten möchten, können Sie das Array möglicherweise in 4-5 Teile aufteilen und diese dann in verschiedene Methoden einteilen. Rufen Sie zum Zeitpunkt des Lesens des Arrays alle Methoden einer Reihe auf. Sie können auch einen Zähler verwalten, um zu wissen, wie viele Indizes Sie analysiert haben.

Vikram Bhardwaj
quelle
0

Dies ist auf den gesamten Code in der Einzelmethodenlösung zurückzuführen: Erstellen Sie mehr kleine Methoden, dann ist dieser Fehler behoben

jaigish
quelle
0

ok, vielleicht ist diese Antwort zu spät, aber ich denke, dieser Weg ist besser als ein anderer

Zum Beispiel haben wir 1000 Zeilendaten im Code

  1. Brich sie

    private void rows500() {
         //you shoud write 1-500 rows here
    }
    
    private void rows1000() {
         you shoud write 500-1000 rows here
    }
  2. Für eine bessere Leistung geben Sie ein "Wenn" in Ihre Codes ein

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

Ich hoffe dieser Code hilft Ihnen

RahimpoorDeveloper
quelle