Erreur de compilation «Code trop volumineux» en Java

94

Existe-t-il une taille maximale pour le code en Java? J'ai écrit une fonction avec plus de 10 000 lignes. En fait, chaque ligne attribue une valeur à une variable de tableau.

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

Et lors de la compilation, j'obtiens cette erreur: code trop volumineux

Comment surmonter cela?

trinité
la source
9
Je suis juste stupéfait ... Il y a forcément une meilleure façon de faire ça.
Thanos Papathanasiou
6
Il faut vraiment regarder une base de données pour ce type de chose, à défaut un fichier de propriétés.
Paul Whelan
44
Pourquoi criez-vous après le pauvre type pour une mauvaise conception? Peut-être qu'OP a obtenu cette méthode insensée par un outil de génération de code.
webuster
14
Je suis abasourdi que ces commentaires critiques superficiels aient obtenu autant de votes positifs!
Evgeni Sergeev
7
Pourquoi le démarrage de votre application passe-t-il beaucoup de temps à analyser un fichier texte alors que le compilateur peut tout pré-générer au moment de la compilation? C'est une mauvaise conception si vous souhaitez modifier les données sans recompiler ou écrire la méthode manuellement, mais ce n'est pas du tout une mauvaise conception si vous générez le code source. (Au moins si vous le faites d'une manière qui permet en fait au compilateur de prégénérer le tableau).
Guntram Blohm soutient Monica

Réponses:

92

Une seule méthode dans une classe Java peut représenter au maximum 64 Ko de bytecode.

Mais vous devriez nettoyer ça!

Utilisez un .propertiesfichier pour stocker ces données et chargez-le viajava.util.Properties

Vous pouvez le faire en plaçant le .propertiesfichier sur votre chemin de classe et en utilisant:

Properties properties = new Properties();
InputStream inputStream = getClass().getResourceAsStream("yourfile.properties");
properties.load(inputStream);
Bozho
la source
2
"Quelle que soit la taille réelle de votre JDK / JVM"? Êtes-vous en train de dire que cette limite n'est pas fixe? Parce qu'il est fixe et requis par la spécification du format de fichier de classe.
Joachim Sauer
1
où puis-je trouver le fichier .properties
trinity
1
vous créez le vôtre puis le mettez sur le chemin des classes
Marc
3
Je n'ai pas utilisé votre suggestion, même si je suis impatient de l'essayer la prochaine fois. J'ai maintenant utilisé une base de données pour stocker ces informations et j'ai modifié le reste du code en conséquence ..
trinity
1
Je suis désolé si c'est une question stupide, mais .. Où doit être placé ce fichier .properties? Je veux dire, ok, c'est dans le chemin des classes, mais où est-il?
Milack27
14

Il existe une limite de taille de 64K octets-code sur un méthode

Cela dit, je suis d'accord avec Richard; pourquoi avez-vous besoin d'une méthode aussi large? Compte tenu de l'exemple dans l'OP, un fichier de propriétés devrait suffire ... ou même une base de données si nécessaire.

Toutes les personnes
la source
4
et les énumérations? J'ai le même problème avec de grands ensembles d'énumérations
Toby
1
@Toby: Je n'ai jamais rencontré ce problème avec enum moi-même. Il y a cependant des articles d'autres utilisateurs ici sur SO sur le même problème. Par exemple - stackoverflow.com/questions/2546470 Il peut être intéressant de regarder dans le fichier .class généré pour enumvoir
Tout
Les instances Enum (c'est-à-dire les objets qui représentent les constantes) sont créées dans l'initialiseur statique de la classe, qui est une méthode et a la même limitation.
juancn
J'ai rencontré le même problème avec le code généré par le framework pour un formulaire Web très complexe. La solution était de diviser le formulaire en composants, de sorte que le code généré pour chaque composant était également divisé.
SebaGra
12

Selon la spécification de la machine virtuelle Java , le code d'une méthode ne doit pas dépasser 65536 octets :

La valeur de l' code_lengthélément donne le nombre d'octets dans le codetableau pour cette méthode.

La valeur de code_length doit être supérieure à zéro (car le tableau de codes ne doit pas être vide) et inférieure à 65536.

code_lengthdéfinit la taille de l' code[]attribut qui contient le bytecode réel d'une méthode:

Le codetableau donne les octets réels du code de la machine virtuelle Java qui implémentent la méthode.

Joachim Sauer
la source
7

Cela ressemble un peu à la folie. Ne pouvez-vous pas initialiser le tableau en lisant les valeurs d'un fichier texte ou d'une autre source de données?

RichardOD
la source
3
(Évalué parce que) Cela nécessite au moins une raison pour laquelle une telle technique est mauvaise. Il n'est pas facile de trouver une bonne raison.
Evgeni Sergeev
2

Essayez de refactoriser votre code. Il y a une limite sur la taille de la méthode en Java.

Padmarag
la source
1
le refactoring n'est pas une idée raisonnable si tout ce qu'il fait dans cette méthode est l'initialisation du tableau.
Gabriel Ščerbák
2
Il a dit que le reste de son code dépend du fait qu'il s'agit d'un tableau. Ainsi, il pourrait refactoriser la méthode pour passer la responsabilité du chargement des données à une autre méthode / usine à partir d'un fichier / base de données.
Padmarag
vous pouvez créer et initialiser de grands tableaux sans recourir à ce genre d'absurdités; voir la réponse de @ Kris.
Stephen C
Refactor - "Processus de modification du code source d'un programme informatique sans modifier son comportement fonctionnel externe afin d'améliorer certains des attributs non fonctionnels du logiciel." En quoi les autres réponses sont-elles différentes de cela?
Padmarag
2

Comme mentionné dans d'autres réponses, il y a une limite de 64 Ko de bytecode pour une méthode (au moins dans le compilateur Java de Sun)

Trop moi, il serait plus logique de diviser cette méthode en plusieurs méthodes - chacune attribuant certaines choses liées au tableau (il serait peut-être plus logique d'utiliser une ArrayList pour ce faire)

par exemple:

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

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

Vous pouvez également charger les éléments à partir d'une ressource statique s'ils sont corrigés comme à partir d'un fichier de propriétés

saret
la source
La bonne réponse est de traiter les données comme des données et le code comme du code.
Malcolm
@Malcolm Eh bien, ce sont clairement des données et non du code. Votre commentaire est trompeur, car il ne faut pas mélanger les données et le code, mais ici, ils ne sont pas mélangés.
Evgeni Sergeev
Je pense que c'est une bonne solution.Je rencontre ce problème avec environ 21k lignes de code avec 7000 messages de route.Je le corrige en divisant ces messages de route en 7 fonctions avec le nom xxx0 xxx1 xxx2.
homme de bronze
2

J'ai moi-même rencontré ce problème. La solution qui a fonctionné pour moi était de refactoriser et de réduire la méthode à des morceaux plus faciles à gérer. Comme vous, j'ai affaire à une méthode de ligne de près de 10K. Cependant, avec l'utilisation de variables statiques ainsi que de fonctions modulaires plus petites, le problème a été résolu.

Il semble qu'il y aurait une meilleure solution de contournement, mais en utilisant Java 8, il n'y en a pas ...

Azadi B.
la source
2

Cette erreur se produit parfois en raison d'un code trop volumineux dans une seule fonction ... Pour résoudre cette erreur, divisez cette fonction en plusieurs fonctions, comme

//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
la source
1

Vous pouvez ajouter une autre méthode pour créer de l'espace pour votre code pour un espace de données supplémentaire, vous pouvez avoir une méthode qui prend une grande quantité d'espace de données. Essayez de diviser vos méthodes car j'ai eu le même problème et corrigez-le en créant une autre méthode supplémentaire pour les mêmes données dans mon code java Android.Le problème a disparu après que je l'ai fait.

FermDroi
la source
C'est plus un commentaire qu'une réponse.
user3071284
0

J'ai une énumération qui fait que la taille du fichier .java dépasse 500 Ko. Eclipse peut le construire pour une raison quelconque; le fichier build.xml ant exporté par éclipse ne peut pas. J'examine ceci et mettrai à jour cet article.

Richard Jessop
la source
0

Comme il y a une limite de taille pour les méthodes et que vous ne voulez pas reconcevoir votre code pour le moment, vous pouvez peut-être diviser le tableau en 4 à 5 parties, puis les mettre en différentes méthodes. Au moment de la lecture du tableau, appelez toutes les méthodes d'une série. Vous pouvez également gérer un compteur pour savoir combien d'index vous avez analysé.

Vikram Bhardwaj
la source
0

cela est dû à tout le code dans une solution de méthodes uniques: créez plus de petites méthodes, puis cette erreur disparaîtra

jaigish
la source
0

ok peut-être que cette réponse est trop tardive mais je pense que cette façon est meilleure qu'une autre, alors

par exemple, nous avons 1000 lignes de données dans le code

  1. Cassez-les

    private void rows500() {
         //you shoud write 1-500 rows here
    }
    
    private void rows1000() {
         you shoud write 500-1000 rows here
    }
  2. pour de meilleures performances, insérez un "si" dans vos codes

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

J'espère que ce code vous aide

Développeur Rahimpoor
la source