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:

  1. montão
  2. Pilha
  3. Code
  4. 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.

Java Pilha e pilha

A variável X em m1 também será criada no quadro para m1 na pilha. (Veja imagem abaixo).

Java Pilha e pilha

O método m1 está chamando o método m2. Na pilha java, um novo quadro é criado para m2 no topo do quadro m1.

Java Pilha e pilha

Java Pilha e pilha

As variáveis ​​bec também serão criadas em um quadro m2 em uma pilha.

public void m2(int b){
boolean c;
}

Java Pilha e pilha

O mesmo método m2 está chamando o método m3. Novamente um frame m3 é criado no topo da pilha (veja a imagem abaixo).

Java Pilha e pilha

Java Pilha e pilha

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.

Java Pilha e pilha

A variável de referência “ref” será criada em uma pilha java.

Java Pilha e pilha

O operador de atribuição “=” fará uma variável de referência para apontar para o objeto no Heap.

Java Pilha e pilha

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.

Java Pilha e pilha

A pilha do método m3 será eliminada.

Java Pilha e pilha

Como a variável de referência não apontará mais para o objeto no heap, ela seria elegível para coleta de lixo.

Java Pilha e pilha

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.

Java Pilha e pilha

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.


Mecanismo de coleta de lixo

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.

Mecanismo de coleta de lixo

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.

Mecanismo de coleta de lixo

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.

Aprenda coletor de lixo

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.

Como excluir um objeto em Java

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.