Erro de compilação “Código muito grande” em Java

94

Existe algum tamanho máximo para o código em Java? Escrevi uma função com mais de 10.000 linhas. Na verdade, cada linha atribui um valor a uma variável de array.

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 a compilação, recebo este erro: código muito grande

Como faço para superar isso?

trindade
fonte
9
Estou chocado ... Deve haver uma maneira melhor de fazer isso.
Thanos Papathanasiou,
6
Você realmente precisa procurar um banco de dados para esse tipo de coisa, na falta de um arquivo de propriedade.
Paul Whelan,
44
Por que vocês estão gritando com o pobre coitado por um projeto ruim? Talvez o OP tenha obtido esse método insano por alguma ferramenta de geração de código.
webuster
14
Estou surpreso que esses comentários críticos superficiais tenham tantos votos positivos!
Evgeni Sergeev
7
Por que a inicialização do seu aplicativo gasta muito tempo analisando algum arquivo de texto quando você pode fazer com que o compilador pré-gere tudo em tempo de compilação? Este é um design ruim se você deseja alterar os dados sem recompilar ou escrever o método manualmente, mas não é um design ruim se você gerar o código-fonte. (Pelo menos se você fizer isso de uma forma que realmente permita que o compilador gere previamente o array).
Guntram Blohm apoia Monica

Respostas:

92

Um único método em uma classe Java pode ter no máximo 64 KB de bytecode.

Mas você deve limpar isso!

Use o .propertiesarquivo para armazenar esses dados e carregue-o viajava.util.Properties

Você pode fazer isso colocando o .propertiesarquivo em seu caminho de classe e usar:

Properties properties = new Properties();
InputStream inputStream = getClass().getResourceAsStream("yourfile.properties");
properties.load(inputStream);
Bozho
fonte
2
"Não importa qual seja o tamanho real do seu JDK / JVM"? Você está insinuando que esse limite não é fixo? Porque é fixo e exigido pela especificação do formato do arquivo de classe.
Joachim Sauer
1
onde posso encontrar o arquivo .properties
trinity
1
você cria o seu próprio e o coloca no caminho de classe
Marcos,
3
Não usei sua sugestão, embora esteja ansioso para tentar da próxima vez .. agora usei um banco de dados para armazenar essas informações e modifiquei o resto do código de acordo ..
trinity
1
Lamento se esta é uma pergunta estúpida, mas ... Onde este arquivo .properties deve ser colocado? Quer dizer, ok, está no caminho de classe, mas onde está?
Milack27
14

Há um limite de tamanho de código de bytes de 64 K em um método

Tendo dito isso, eu tenho que concordar com Richard; por que você precisa de um método tão grande? Dado o exemplo no OP, um arquivo de propriedades deve ser suficiente ... ou mesmo um banco de dados, se necessário.

Todos
fonte
4
que tal enums? Tenho o mesmo problema com grandes conjuntos de enums
Toby
1
@Toby: Nunca enfrentei esse problema com enum. No entanto, há postagens de outros usuários aqui no SO sobre o mesmo assunto. Por exemplo - stackoverflow.com/questions/2546470 Pode valer a pena olhar para o arquivo .class gerado enumpara ver
Todos
Instâncias de Enum (ou seja, os objetos que representam as constantes) são criadas no inicializador estático da classe, que é um método e tem a mesma limitação.
2015
Eu enfrentei o mesmo problema com o código gerado pelo framework para um formulário da web realmente complexo. A solução foi dividir o formulário em componentes, de forma que o código gerado para cada componente também fosse dividido.
SebaGra
12

De acordo com a especificação da Java Virtual Machine , o código de um método não deve ser maior que 65536 bytes :

O valor do code_lengthitem fornece o número de bytes na codematriz para este método.

O valor de code_length deve ser maior que zero (já que a matriz de código não deve estar vazia) e menor que 65536.

code_lengthdefine o tamanho do code[]atributo que contém o bytecode real de um método:

O codearray fornece os bytes reais do código da Java Virtual Machine que implementa o método.

Joachim Sauer
fonte
7

Isso parece um pouco loucura. Você não pode inicializar a matriz lendo os valores de um arquivo de texto ou alguma outra fonte de dados?

RichardOD
fonte
3
(Votos negados porque) Isso precisa de pelo menos uma razão pela qual tal técnica é ruim. Não é fácil inventar um bom motivo.
Evgeni Sergeev
2

Tente refatorar seu código. Há limite para o tamanho do método em Java.

Padmarag
fonte
1
a refatoração não parece uma ideia razoável se tudo o que ele faz nesse método é a inicialização do array.
Gabriel Ščerbák,
2
Ele disse que o resto de seu código depende de ser um array. Assim, ele poderia refatorar o método para passar a responsabilidade de carregar os dados para algum outro método / fábrica do arquivo / banco de dados.
Padmarag,
você pode criar e inicializar grandes arrays sem recorrer a esse tipo de absurdo; veja a resposta de @Kris.
Stephen C,
Refatorar - "Processo de alterar o código-fonte de um programa de computador sem modificar seu comportamento funcional externo para melhorar alguns dos atributos não funcionais do software." Como outras respostas são diferentes desta?
Padmarag
2

Conforme mencionado em outras respostas, há um limite de 64 KB de bytecode para um método (pelo menos no compilador java da Sun)

Para mim, faria mais sentido quebrar esse método em mais métodos - cada um atribuindo certas coisas relacionadas ao array (pode fazer mais sentido usar um ArrayList para fazer isso)

por exemplo:

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

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

Alternativamente, você pode carregar os itens de um recurso estático se eles forem corrigidos como em um arquivo de propriedades

saret
fonte
A resposta correta é tratar os dados como dados e o código como código.
Malcolm
@Malcolm Bem, isso são claramente dados, e não código. Seu comentário é enganoso, porque o que você não deve fazer é misturar dados e código, mas aqui eles não estão misturados.
Evgeni Sergeev
Eu acho que esta é uma boa solução. Vejo esse problema com cerca de 21k linhas de código com 7000 mensagens de rota. Eu conserto por div essas mensagens de rota em 7 funções com o nome xxx0 xxx1 xxx2.
homem de bronze de
2

Eu mesmo tive esse problema. A solução que funcionou para mim foi refatorar e reduzir o método a partes mais gerenciáveis. Como você, estou lidando com um método de quase 10K linhas. Porém, com o uso de variáveis ​​estáticas e também de funções modulares menores, o problema foi resolvido.

Parece que haveria uma solução alternativa melhor, mas usando Java 8, não há nenhuma ...

Azadi B.
fonte
2

Este erro às vezes ocorre devido a um código muito grande em uma única função ... Para resolver esse erro, divida essa função em várias funções, como

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

Você pode adicionar outro método para criar espaço para seu código para espaço de dados adicional, você pode ter um método que está ocupando uma grande quantidade de espaço de dados. Tente dividir seus métodos porque tive o mesmo problema e corrija-o criando outro método adicional para os mesmos dados em meu código Java Android. O problema foi embora depois que fiz isso.

FermDroi
fonte
Isso é mais um comentário do que uma resposta.
user3071284
0

Eu tenho um enum que faz com que o arquivo .java tenha mais de 500 KB. O Eclipse pode construí-lo por algum motivo; o ant build.xml exportado por eclipse não pode. Estou analisando isso e atualizarei este post.

Richard Jessop
fonte
0

Como há um limite de tamanho para métodos e você não quer redesenhar seu código neste momento, pode ser que você possa dividir o array em 4-5 partes e depois colocá-las em métodos diferentes. No momento da leitura do array, chame todos os métodos em uma série. Você também pode manter um contador para saber quantos índices analisou.

Vikram Bhardwaj
fonte
0

isso é devido a todo o código na solução de método único: crie mais alguns métodos pequenos, então este erro desaparecerá

jaigish
fonte
0

ok talvez esta resposta seja tarde demais, mas eu acho que esse jeito é melhor do que outro então

por exemplo, temos dados de 1000 linhas no código

  1. quebrá-los

    private void rows500() {
         //you shoud write 1-500 rows here
    }
    
    private void rows1000() {
         you shoud write 500-1000 rows here
    }
  2. para um melhor desempenho, coloque um "se" em seus códigos

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

Espero que este código ajude você

RahimpoorDeveloper
fonte