Errore di compilazione "Codice troppo grande" in Java


94

Esiste una dimensione massima per il codice in Java? Ho scritto una funzione con più di 10.000 righe. In realtà, ogni riga assegna un valore a una variabile di matrice.

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

E durante la compilazione, ottengo questo errore: codice troppo grande

Come posso superarlo?


9
Sono solo sbalordito ... Ci sarà sicuramente un modo migliore per farlo.
Thanos Papathanasiou

6
Hai davvero bisogno di guardare un database per questo tipo di cose, in mancanza di un file di proprietà.
Paul Whelan

44
Perché ragazzi urlate al poveretto per cattivo design? Forse OP ha ottenuto quel metodo folle da qualche strumento di generazione di codice.
webuster

14
Sono sbalordito che questi commenti critici superficiali abbiano ricevuto così tanti voti positivi!
Evgeni Sergeev

7
Perché l'avvio dell'applicazione impiega molto tempo ad analizzare alcuni file di testo quando è possibile fare in modo che il compilatore pre-generi tutto in fase di compilazione? Questo è un cattivo design se vuoi cambiare i dati senza ricompilare, o scrivere il metodo manualmente, ma non è affatto un cattivo design se generi il codice sorgente. (Almeno se lo fai in un modo che consenta effettivamente al compilatore di pregenerare l'array).
Guntram Blohm sostiene Monica

Risposte:


92

Un singolo metodo in una classe Java può essere al massimo 64 KB di bytecode.

Ma dovresti ripulirlo!

Usa .propertiesfile per memorizzare questi dati e caricali tramitejava.util.Properties

Puoi farlo inserendo il .propertiesfile nel tuo classpath e usa:

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

2
"Non importa quale sia la dimensione effettiva del tuo JDK / JVM"? Stai insinuando che questo limite non è fisso? Perché è fisso e richiesto dalla specifica del formato del file di classe.
Joachim Sauer

1
dove posso trovare il file .properties
trinity

1
crei il tuo e poi lo metti sul classpath
Marco

3
non ho utilizzato il tuo suggerimento, anche se sono ansioso di provarlo la prossima volta .. ora ho usato un database per memorizzare queste informazioni e ho modificato il resto del codice di conseguenza ..
trinity

1
Mi dispiace se questa è una domanda stupida, ma .. Dove dovrebbe essere messo questo file .properties? Voglio dire, ok, è nel classpath, ma dov'è?
Milack27

14

Esiste un limite di dimensione del codice byte 64 KB su un metodo

Detto questo, sono d'accordo con Richard; perché hai bisogno di un metodo così ampio? Dato l'esempio nell'OP, dovrebbe essere sufficiente un file delle proprietà ... o anche un database, se necessario.


4
che ne dici di enumerazioni? ottengo lo stesso problema con grandi serie di enumerazioni
Toby

1
@Toby: Non ho mai affrontato questo problema con enum da solo. Tuttavia, ci sono post di altri utenti qui su SO sullo stesso problema. Ad esempio - stackoverflow.com/questions/2546470 Potrebbe essere utile esaminare il file .class generato per enumvederlo
Tutti

Le istanze di Enum (cioè gli oggetti che rappresentano le costanti) vengono create nell'inizializzatore statico della classe, che è un metodo e ha la stessa limitazione.
giovedì

Ho affrontato lo stesso problema con il codice generato dal framework per un modulo web davvero complesso. La soluzione era suddividere il modulo in componenti, quindi anche il codice generato per ogni componente è stato diviso.
SebaGra

12

Secondo la specifica Java Virtual Machine , il codice di un metodo non deve essere più grande di 65536 byte :

Il valore di code_length dell'elemento fornisce il numero di byte codenell'array per questo metodo.

Il valore di code_length deve essere maggiore di zero (poiché la matrice del codice non deve essere vuota) e minore di 65536.

code_lengthdefinisce la dimensione code[]dell'attributo che contiene il bytecode effettivo di un metodo:

L' codearray fornisce i byte effettivi del codice Java Virtual Machine che implementa il metodo.


7

Sembra un po 'una follia. Non puoi inizializzare l'array leggendo i valori da un file di testo o da qualche altra fonte di dati?


3
(Downvoted because) Questo richiede almeno un motivo per cui una tale tecnica è cattiva. Non è facile trovare una buona ragione.
Evgeni Sergeev

2

Prova a eseguire il refactoring del codice. Esiste un limite alla dimensione del metodo in Java.


1
il refactoring non sembra un'idea ragionevole se tutto ciò che fa in quel metodo è l'inizializzazione dell'array.
Gabriel Ščerbák

2
Ha detto che il resto del suo codice dipende dal fatto che questo sia un array. Quindi potrebbe eseguire il refactoring del metodo per passare la responsabilità del caricamento dei dati a un altro metodo / Factory da file / database.
Padmarag

è possibile creare e inizializzare array di grandi dimensioni senza ricorrere a questo tipo di sciocchezze; vedi la risposta di @ Kris.
Stephen C

Refactor - "Processo di modifica del codice sorgente di un programma per computer senza modificare il suo comportamento funzionale esterno al fine di migliorare alcuni degli attributi non funzionali del software." In che modo le altre risposte sono diverse da questa?
Padmarag

2

Come accennato in altre risposte, esiste un limite di 64 KB di bytecode per un metodo (almeno nel compilatore java di Sun)

Anche per me avrebbe più senso suddividere quel metodo in più metodi, ognuno dei quali assegna determinate cose correlate all'array (potrebbe avere più senso usare un ArrayList per farlo)

per esempio:

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

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

In alternativa è possibile caricare gli elementi da una risorsa statica se sono corretti come da un file delle proprietà


La risposta corretta è trattare i dati come dati e il codice come codice.
Malcolm

@Malcolm Bene, questi sono chiaramente dati e non codice. Il tuo commento è fuorviante, perché quello che non dovresti fare è mescolare dati e codice, ma qui non sono mescolati.
Evgeni Sergeev

Penso che questo sia un buon lavoro, mi imbatto in questo problema con circa 21k righe di codice con 7000 messaggi di instradamento al suo interno, lo risolvo dividendo quei messaggi di instradamento in 7 funzioni con nome xxx0 xxx1 xxx2.
uomo di bronzo

2

Mi sono imbattuto in questo problema da solo. La soluzione che ha funzionato per me è stata il refactoring e la riduzione del metodo a parti più gestibili. Come te, ho a che fare con un metodo di quasi 10K linee. Tuttavia, con l'uso di variabili statiche e funzioni modulari più piccole, il problema è stato risolto.

Sembra che ci sarebbe una soluzione migliore, ma usando Java 8, non ce n'è ...


2

Questo errore a volte si verifica a causa di un codice troppo grande in una singola funzione ... Per risolvere quell'errore, dividi quella funzione in più funzioni, come

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

Puoi aggiungere un altro metodo per creare spazio per il tuo codice per ulteriore spazio dati, potresti avere un metodo che occupa una grande quantità di spazio dati. Prova a dividere i tuoi metodi perché ho avuto lo stesso problema e risolverlo creando un altro metodo aggiuntivo per gli stessi dati nel mio codice Android Java, Il problema era scomparso dopo averlo fatto.


Questo è più un commento che una risposta.
user3071284

0

Ho un enum che fa sì che il file .java abbia una dimensione superiore a 500 KB. Eclipse può costruirlo per qualche motivo; l'ant build.xml esportato da eclipse non può. Sto esaminando questo e aggiornerò questo post.


0

Poiché esiste un limite di dimensione per i metodi e non si desidera ridisegnare il codice in questo momento, potrebbe essere possibile dividere l'array in 4-5 parti e quindi inserirle in metodi diversi. Al momento della lettura dell'array, chiama tutti i metodi in una serie. Puoi anche mantenere un contatore per sapere quanti indici hai analizzato.


0

ciò è dovuto a tutto il codice nella soluzione dei metodi singoli: creare più metodi piccoli, quindi questo errore sarà scomparso


0

ok forse questa risposta è troppo tardi ma penso che in questo modo sia meglio di un altro modo

ad esempio, abbiamo 1000 righe di dati nel codice

  1. romperli

    private void rows500() {
         //you shoud write 1-500 rows here
    }
    
    private void rows1000() {
         you shoud write 500-1000 rows here
    }
  2. per prestazioni migliori, inserire un "se" nei codici

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

Spero che questo codice ti aiuti

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.