Gerenciamento de memória em Java
O que é memória de pilha?
Stack em java é uma seção de memória que contém métodos, variáveis locais e variáveis de referência. A memória da pilha é sempre referenciada na ordem Last-In-First-Out. Variáveis locais são criadas na pilha.
O que é memória heap?
Heap é uma seção da memória que contém Objetos e também pode conter variáveis de referência. Variáveis de instância são criadas no heap.
Alocação de memória em Java
Alocação de memória em Java é o processo no qual as seções da memória virtual são reservadas em um programa para armazenamento de variáveis e instâncias de estruturas e classes. Entretanto, a memória não é alocada para um objeto na declaração, mas apenas uma referência é criada. Para a alocação de memória do objeto, o método new() é usado, de forma que o objeto sempre tenha memória alocada no heap.
O Java A alocação de memória é dividida nas seguintes seções:
- montão
- Pilha
- Code
- Estático
Esta divisão da memória é necessária para o seu gerenciamento eficaz.
- O código seção contém seu bytecode.
- O Pilha seção de memória contém métodos, variáveis locais e variáveis de referência.
- O montão seção contém objetos (também pode conter variáveis de referência).
- O Estático seção contém Dados/métodos estáticos.
Diferença entre variável local e de instância
Variável de instância é declarado dentro de uma classe, mas não dentro de um método
class Student{ int num; // num is instance variable public void showData{}
Variável local são declarados dentro a método incluindo método argumentos.
public void sum(int a){ int x = int a + 3; // a , x are local variables; }
Diferença entre pilha e heap
Clique aqui se o vídeo não estiver acessível
Vamos dar um exemplo para entender isso melhor. Considere que seu método principal está chamando o método m1
public void m1{ int x=20 }
Na pilha java, um quadro será criado a partir do método m1.
A variável X em m1 também será criada no quadro para m1 na pilha. (Veja imagem abaixo).
O método m1 está chamando o método m2. Na pilha java, um novo quadro é criado para m2 no topo do quadro m1.
As variáveis bec também serão criadas em um quadro m2 em uma pilha.
public void m2(int b){ boolean c; }
O mesmo método m2 está chamando o método m3. Novamente um frame m3 é criado no topo da pilha (veja a imagem abaixo).
Agora digamos que nosso método m3 esteja criando um objeto para a classe “Conta”, que possui dois variável de instâncias int p e int q.
Account { Int p; Int q; }
Aqui está o código para o método m3
public void m3(){ Account ref = new Account(); // more code }
A instrução new Account() criará um objeto de conta no heap.
A variável de referência “ref” será criada em uma pilha java.
O operador de atribuição “=” fará uma variável de referência para apontar para o objeto no Heap.
Uma vez que o método tenha completado sua execução. O fluxo de controle retornará ao método de chamada. Que neste caso é o método m2.
A pilha do método m3 será eliminada.
Como a variável de referência não apontará mais para o objeto no heap, ela seria elegível para coleta de lixo.
Uma vez que o método m2 tenha completado sua execução. Ele será retirado da pilha, e todas as suas variáveis serão esvaziadas e não estarão mais disponíveis para uso.
Da mesma forma para o método m1.
Eventualmente, o fluxo de controle retornará ao ponto inicial do programa. Que geralmente é o método “principal”.
E se Object tiver uma referência como variável de instância?
public static void main(String args[]) { A parent = new A(); //more code } class A{ B child = new B(); int e; //more code } class B{ int c; int d; //more code }
Neste caso, a variável de referência “filho” será criada no heap, que por sua vez estará apontando para o seu objeto, algo como o diagrama mostrado abaixo.
Em que consiste a coleta de lixo Java?
Coleta de lixo em Java é um processo pelo qual os programas realizam o gerenciamento de memória automaticamente. O Coletor de Lixo (GC) encontra os objetos não utilizados e os exclui para recuperar a memória. Em Java, a alocação dinâmica de memória de objetos é obtida usando o novo operador que usa alguma memória e a memória permanece alocada até que haja referências para o uso do objeto.
Quando não há referências a um objeto, presume-se que ele não seja mais necessário e a memória ocupada pelo objeto pode ser recuperada. Não há necessidade explícita de destruir um objeto como Java lida com a desalocação automaticamente.
A técnica que faz isso é conhecida como Coleta de lixo. Os programas que não desalocam memória podem eventualmente travar quando não houver mais memória no sistema para alocar. Diz-se que estes programas têm perda de memória. Coleta de lixo em Java acontece automaticamente durante a vida útil do programa, eliminando a necessidade de desalocar memória e evitando assim vazamentos de memória.
Na linguagem C, é responsabilidade do programador desalocar a memória alocada dinamicamente usando a função free(). É aqui que Java leads de gerenciamento de memória.
Nota: Todos os objetos são criados na Heap Section da memória. Mais sobre isso em um tutorial posterior.
Exemplo: Para aprender o mecanismo de coleta de lixo em Java
Passo 1) Copie o código a seguir em um editor.
class Student{ int a; int b; public void setData(int c,int d){ a=c; b=d; } public void showData(){ System.out.println("Value of a = "+a); System.out.println("Value of b = "+b); } public static void main(String args[]){ Student s1 = new Student(); Student s2 = new Student(); s1.setData(1,2); s2.setData(3,4); s1.showData(); s2.showData(); //Student s3; //s3=s2; //s3.showData(); //s2=null; //s3.showData(); //s3=null; //s3.showData(); } }
Passo 2) Salve, compile e execute o código. Conforme mostrado no diagrama, dois objetos e duas variáveis de referência são criados.
Passo 3) Remova o comentário da linha # 20,21,22. Salve, compile e execute o código.
Passo 4) Conforme mostrado no diagrama abaixo, duas variáveis de referência apontam para o mesmo objeto.
Passo 5) Remova o comentário das linhas 23 e 24. Compile, salve e execute o código
Passo 6) Conforme mostrado no diagrama abaixo, s2 se torna nulo, mas s3 ainda está apontando para o objeto e não é elegível para coleta de lixo java.
Passo 7) Remova o comentário das linhas 25 e 26. Salve, compile e execute o código
Passo 8) Neste ponto não há referências apontando para o objeto e torna-se elegível para coleta de lixo. Ele será removido da memória e não há como recuperá-lo.
Como excluir um objeto em Java?
1) Se você deseja tornar seu objeto elegível para coleta de lixo, atribua sua variável de referência como nula.
2) Os tipos primitivos não são objetos. Eles não podem ser atribuídos como nulos.
Resumo:
- Quando um método é chamado, um quadro é criado no topo da pilha.
- Depois que um método conclui a execução, o fluxo de controle retorna ao método chamador e seu quadro de pilha correspondente é liberado.
- Variáveis locais são criadas na pilha
- Variáveis de instância são criadas no heap e fazem parte do objeto ao qual pertencem.
- Variáveis de referência são criadas na pilha.