Exception in thread main java.lang.OutOfMemoryError: Java heap space

9 respostas
J

Ola , a Todos

Estava com um problema , fiz um Programa para carregar um arquivo txt como um bloco de nota, que funcionava muito bem com arquivos pequenos , porem quando o arquivo é muito grande , aparecia o seguinte erro = [color=red]Exception in thread ?main? java.lang.OutOfMemoryError: Java heap space [/color], depois de algum tempo achei uma possivel solução conforme abaixo

Abaixo explicação

Qual o programador java que nunca teve um java.lang.OutOfMemoryError ?????

Vamos ver como podemos contornar isso? mas para tanto, teremos de entender como funciona o uso de memória nas aplicações Java.

Para a prova SCJP, temos de entender que existem dois tipos de memória no Java: a Stack e a Heap. Mas este conceito é muito abstrato: na realidade, existem mais tipos de memória no Java, sendo que as mesmas possuem sub-seções. Abaixo, cada uma delas:

Stack: É a pilha de execução. Cada método executado é colocado na pilha. Desta forma, o nível mais baixo desta pilha é o inicio de uma Thread (o metodo main é inciado por uma Thread).

Heap: É o local onde ficam os objetos instanciados. É dividida em três partes: a ?Eden Space?(ou Young Gen), a ?Survivor Space? e a ?Tenured Gen?(ou Old Gen).

Permanent Generation: Local onde ficam os dados de reflexão da prórpia máquina virtual, dados de classe e de métodos. É dividida em áreas de leitura/escrita ou somente leitura.

Code Cache: Contém memória para compilar e guardar códigos nativos.

Mais sobre a Heap

Aqui é onde os objetos são instanciados. Logo de cara, todo objeto instanciado vai para a Eden Space. Normalmente, o objeto morre ali mesmo. Quando é efetuado uma Garbage Collection, os objetos da Eden Space que ainda possuem referência são movidos para alguma das Survivor Spaces (existem duas). Os caras que ficarem muito tempo ?vivos? na Survivor Space são movidos para a Ternured Space. Por isso a Ternured Space é o maior espaço de memória da Heap.

Vamos fazer um pequeno teste. Olhe o código abaixo:

01 import java.util.ArrayList;

02 import java.util.List;

03

04 /**

05 *

06 * @author Amarildo

07 */

08 public class Main {

09

10 public static void main(String[] args) {

11

12 List lista = new ArrayList();

13

14 for ( int i = 0; i < 8000000; i++ ){

15 lista.add( ?TESTES TESTES? );

16 }

17 }

18 }

Ele instancia uma lista com ?apenas? 8 milhões de Strings. Ao executar:

java Main

Exception in thread ?main? java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2760)
at java.util.Arrays.copyOf(Arrays.java:2734)
at java.util.ArrayList.ensureCapacity(ArrayList.java:167)
at java.util.ArrayList.add(ArrayList.java:351)
at testes.Main.main(Main.java:25)
Java Result: 1

Tcham tcham tcham tcham!!! Pelo motivo do erro, podemos perceber que o problema esta na HEAP: a VM praticamente diz: ?Ow mané! Ta faltando Heap Space aqui pra isso pow!?

Vamos executar novamente, agora desta forma:

java -Xmx128m Main

?

Não deu problema! Mas? o que que houve? Simples: passamos para a JVM que, para esta execução, alocaremos NO MÁXIMO 128 mb ao invés do 64 mb default que ela permite usar. Outro parâmetro interessante é o Xmx: ele define a memória mínima para a execução. Desta forma:

java -Xms64m -Xmx128m Main

Com o comando acima, definimos de 64 mb de memória serão alocados diretamente para esta aplicação, mesmo que a mesma utilize apenas 1 mb. E caso 64 mb não sejam suficientes, ela pode usar ATÉ 128 mb. Caso ultrapasse os 128 mb, irá lançar um gostoso ?java.lang.OutOfMemoryError: Java heap space?. Hehehe!

Ta? e o meu Eclipse? Onde altero isso?
No diretório onde o Eclipse está instalado, tem um arquivo chamado eclipse.ini, que contém os parâmetros da JVM. Caso esteja vazio ou não contenha estes parâmetros, basta adicionar (exemplo abaixo):
-vmargs
-Xms128m
-Xmx512m

E no NetBeans???
deve-se clicar com o botão direito do mouse em cima do ícone que vai o nome do PROJETO no NetBeans
e clicar sobre a opção PROPERTIES do menu suspenso. Lá existe uma divisão de opções onde uma delas é "RUN = Executar". Em
"Run = Executar" há um campo de texto chamado "VM OPTIONS = Opções da VM", onde eu inseri: "-Xms256m -Xmx512m".

E no JEdit?
O JEdit normalmente não precisa de muita memória? mas as vezes, ao trabalhar com um arquivo muito grande, pode-se ter problemas. O JEdit é na mão grande mesmo: não tem arquivo de configuração:
Da pra alterar o atalho da área de trabalho:
$JDK_HOME\bin\javaw.exe -Xmx128m -Xms256m -jar ?$JEDIT_HOME\jedit.jar?
onde JDK_HOME é o diretorio do JDK e o JEDIT_HOME é o diretório do JEDIT
ou pela linha de comando mesmo:
java -Xmx128m -Xms128m -jar jedit.jar

E o meu Tomcat??
Dentro do catalina.sh (ou catalina.bat para windows) basta criar a variável CATALINA_OPTS ou JAVA_OPTS e adicionar os parâmetros:
CATALINA_OPTS=?-Xms256m -Xmx512m? ou
JAVA_OPTS=?-Xms256m -Xmx512m?

-----------------------------------------------------------------------

porem as Opções Acima só irão funcionar na execução feita na Ide , fora dela ou seja na execução pelo arquivo jar
terá que ser criado um bat exemplo Abaixo

[size=18]Uso a Ide NetBeans 6.1 , Quando já estava feliz pensando que Tinha achado Resposta para o Problema , Foi so gerar o .jar para descobrir que as alterção funciona somente na Ide , fora dela continua o mesmo erro conclusão vou mandar a Ide para o usuario conseguir usar o Programa brincadeira, porem preciso de uma solução .... Grato pela atenção [/size]

---------------------------------- começo arquivo Bat
rem @echo off
rem ---------------------------------------------------------------------
rem - NAME: Projeto.bat
rem - NOTE: aumentar a Memoria da JVM para poder executar o projeto
rem ---------------------------------------------------------------------

set C:\;"caminho do projeto"
java -jar -Xms256m -Xmx512m Projeto.jar
----------------------------------- Final Arquivo Bat

Porem está difícil acreditar que essa é a única solução , estou enviando parte do Codigo , caso alguem saiba porque o codigo esta consumindo
tanta memoria por favor me avise
att Javax_javaX

botao1.addActionListener(new ActionListener(){                          
        public void actionPerformed(ActionEvent Clik){                                                     
              ProgressBar.setValue(0);
              //JFileChooser fileChooser = new JFileChooser("."); 
              JFileChooser fileChooser = new JFileChooser(); 
              fileChooser.showOpenDialog(tela);
              File arquivo_Entrada = fileChooser.getSelectedFile();
               
            if (arquivo_Entrada != null){
                 
                 textArea1.setText("");
                 String s = LeitorBuffer.ler(arquivo_Entrada);
                 textArea1.append(s);
                 textArea1.setCaretPosition(0); // Mantem o Cursor no inicio 

                 arquivo_Entrada = null;
                 s = null;
                 fileChooser = null;
                 
                 System.gc();
                 
                  int quant = textArea1.getLineCount();
                  maxValue=quant;
                  ProgressBar.setMaximum(maxValue-2);
                 
                  for(int j = 0; j < quant; j++){
                  final int percent = j;
                  // Função Para Barra de Processamento Começo
                     ProgressBar.setValue(percent); 
                     //ProgressBar.setIndeterminate(true);  // Este Comanado Faz Com que a Barra de Processamento Fique de um Lado Para o Outro Até o Fim do Processo              
                  // Função Para Barra de Processamento final            
                }
            }
               
                
                System.out.println("1º total de memoria ? :"+Runtime.getRuntime().maxMemory());     
         
                System.out.println("2º quanto estou usando de memoria ?:"+Runtime.getRuntime().totalMemory());     
           
                System.out.println("3º quanto ainda tenho de memoria ?:"+Runtime.getRuntime().freeMemory());   


        }
    });

segue link com Ótimas dicas http://www.argonavis.com.br/cursos/java/j190/TutorialGerenciaMemoriaJava.pdf

9 Respostas

R

Você pode editar um .bat ou .sh com o comando adequado para executar o seu programa. Assim você pode passar os parâmetros de memória na chamada do JVM. Também é interessante você examinar o seu programa para saber se você está liberando recursos de maneira apropriada.

J

Muito Obrigado pela sua atenção rmendes08 ,é muito util , porem gostaria de fazer algo com implementação Direto no codigo , ou algo to tipo puxar as configurações alteradas no Netbeans direto para o arquivo.jar , mais para tratar o problema de maneira mais elegante … creio que deva ter alguma solução , caso contrario , seguirei sua instrução .

[size=18][color=red]mais uma vez muito Obrigado[/color][/size]

V

Nunca entendi pq não enfiaram esse tipo de configuração em algum tipo de arquivo manifesto do .jar.
Não há como, você deve criar um .bat mesmo. É feio, ridículo, mas é assim que funciona.

J

Grato ViniGodoy , é o que parece mesmo, tenho pesquisado e a unica solução me apresentanda é mesmo criar o bat , tbm não consigo entender como deixaram passar isso, uma linguagem tão robusta.

de qualquer forma

[size=18][color=red]Muito Obrigado[/color][/size]

C

Dae galera… seguinte, tenho 3gb de RAM aqui no meu PC.

Em outro artigo, peguei estas configurações para o eclipse.ini:

-vmargs
-Xms1024m
-Xmx1024m
-XX:PermSize=512m
-XX:MaxPermSize=512m

O -XMs e o -Xms funcionaram com 1024, mas não mais que isso para meus 3gb de RAM. Pra falar a verdade consegui no máximo 1060m pra estes. E nos -XX:PermSize e -XX:MaxPermSize consegui no máximo 384.

Alguém saberia me informar quais são as regras entre as relações destes parâmetros e a memória RAM total no PC ???

Obrigado.

A

Amigos,

Apesar do razoável tempo transcorrido desde a última mensagem, preciso tirar uma dúvida sobre o assunto.

No caso de uma aplicação java desktop distribuída via Java Web Start (JWS), como aumentar a quantidade de memória disponível para o programa? É possível?

Saudações.

L

Oi,

Pensem: Nem sempre aumentar a memória virtual é a melhor solução.

Tchauzin!

A

lina:
Oi,

Pensem: Nem sempre aumentar a memória virtual é a melhor solução.

Tchauzin!

Como então contornar a seguinte situação?

byte[] conteudoArquivo = new byte[tamanhoArquivo];

No trecho acima, tamanhoArquivo pode variar de poucas dezenas até um número da ordem de milhões.

L

andredf:
lina:
Oi,

Pensem: Nem sempre aumentar a memória virtual é a melhor solução.

Tchauzin!

Como então contornar a seguinte situação?

byte[] conteudoArquivo = new byte[tamanhoArquivo];

No trecho acima, tamanhoArquivo pode variar de poucas dezenas até um número da ordem de milhões.

Oi,

Você pode ler em pedaços + pedaços e não o arquivo completo tudo de uma vez.

Tchauzin!

Criado 6 de abril de 2010
Ultima resposta 7 de fev. de 2013
Respostas 9
Participantes 6