Gerenciamento de memória em Java

⚡ Resumo Inteligente

Gerenciamento de memória em Java Explica como a JVM divide a memória de tempo de execução entre Pilha, Heap, Code, e regiões estáticas, como as referências de objetos fluem durante as chamadas de método e como o coletor de lixo recupera objetos inacessíveis para que os aplicativos permaneçam estáveis ​​e livres de vazamentos de memória.

  • 🧠 Layout da memória da JVM: Java A memória é dividida em Heap para objetos, Stack para frames de métodos e variáveis ​​locais, além de áreas dedicadas para bytecode e dados estáticos.
  • 📚 Pilha vs. Heap: Os frames da pilha seguem a ordem LIFO (último a entrar, primeiro a sair) e armazenam tipos primitivos e referências, enquanto o Heap armazena todos os objetos criados com o operador new.
  • ♻️ Coleta de lixo: O coletor de lixo tracO ks garante acessibilidade por meio de cadeias de referência e recupera automaticamente a memória de objetos que nenhuma thread consegue alcançar.
  • Colecionadores modernos: As cargas de trabalho de produção dependem cada vez mais do G1, ZGC e Shenandoah para coleta com poucas pausas em heaps de vários gigabytes.
  • 🧪 Exemplo prático: Um passo a passo da classe Student mostra quando as referências se tornam elegíveis para coleta e como anular referências libera o objeto subjacente.

Gerenciamento de memória em Java

O que é memória de pilha em Java?

Memória de pilha em Java A pilha é a região da memória da JVM que armazena frames de métodos, variáveis ​​locais e variáveis ​​de referência para cada thread. O acesso à pilha é sempre feito na ordem LIFO (último a entrar, primeiro a sair), portanto, o método invocado mais recentemente fica no topo, e suas variáveis ​​locais são adicionadas e removidas junto com o frame.

Cada fio no Java A Máquina Virtual recebe sua própria Pilha, o que mantém as invocações de métodos isoladas e seguras para uso em múltiplas threads por design. Variáveis ​​locais primitivas, como int, boolean e double, residem diretamente dentro do frame, enquanto as referências a objetos armazenadas na Pilha apontam para objetos alocados no Heap.

O que é memória Heap em Java?

A memória heap é a região compartilhada da JVM que armazena todos os dados. Java Objetos e arrays criados com o operador `new`, juntamente com quaisquer variáveis ​​de referência que pertençam a esses objetos como campos de instância. Ao contrário da pilha, o heap é compartilhado entre todas as threads, razão pela qual o acesso a objetos geralmente requer sincronização.

O Heap é a área gerenciada pelo coletor de lixo. As JVMs HotSpot modernas dividem o Heap em uma Geração Jovem para objetos de curta duração e uma Geração Antiga para objetos de longa duração, com os metadados de classe armazenados em uma região nativa separada chamada Metaspace.

Alocação de memória em Java

Alocação de memória em Java É o processo pelo qual a JVM reserva regiões de memória virtual para variáveis ​​e instâncias de classes e estruturas durante a execução do programa. A memória não é alocada a um objeto na declaração; apenas uma referência é criada. A alocação real do objeto ocorre por meio do operador `new`, portanto, cada objeto reside no Heap.

O Java A alocação de memória é dividida nas seguintes seções:

  1. montão
  2. CorMonitor
  3. Code
  4. Estático

Essa divisão de memória é necessária para o gerenciamento eficaz do ambiente de execução.

  • O Code Esta seção contém seu arquivo compilado. bytecode.
  • O CorMonitor lojas de seção métodos, variáveis ​​locais e variáveis ​​de referência.
  • O montão seção contém objetos e também podem conter variáveis ​​de referência armazenadas como campos de instância.
  • O Estático seção contém dados estáticos e métodos estáticos Compartilhado em todas as instâncias.

Diferença entre variável local e de instância

Entender onde cada tipo de variável reside na JVM ajuda a explicar o comportamento da pilha e do heap. variável de instância é declarado dentro de uma classe, mas fora de qualquer método.e reside no Heap como parte de seu objeto.

class Student{ 
int num; // num is instance variable 
public void showData{}

A variável local é declarado dentro de um método, incluindo argumentos do métodoe reside na pilha dentro do quadro ativo.

public void sum(int a){

int x = a + 3;

// a, x are local variables

}

Diferença entre pilha e heap

A pilha (Stack) e o heap resolvem problemas diferentes dentro da JVM. A pilha fornece a cada thread uma alocação rápida e determinística para dados de curta duração vinculados ao escopo do método, enquanto o heap fornece uma região compartilhada para objetos de longa duração que qualquer thread pode referenciar. O breve vídeo abaixo resume o contraste antes da explicação detalhada que se segue.

Clique aqui. se o vídeo não estiver acessível

Para ver como a pilha e o heap cooperam, considere um método principal que chama o método m1.

public void m1{
int x = 20;
}

Na pilha da JVM, um frame é criado para o método m1.

Java Pilha e pilha

A variável x em m1 também é criada no frame de m1 na pilha, como mostrado na imagem abaixo.

Java Pilha e pilha

O método m1 chama então o método m2. Na pilha, um novo frame é criado para m2 acima do frame de m1.

Java Pilha e pilha

Java Pilha e pilha

As variáveis ​​locais b e c também são criadas dentro do frame para m2 na pilha.

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

Em seguida, m2 chama o método m3. Novamente, um frame para m3 é criado no topo da pilha, como mostrado abaixo.

Java Pilha e pilha

Java Pilha e pilha

Agora, suponha que o método m3 crie um objeto para a classe Account, que possui dois variáveis ​​de instância int p e int q.

class 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()` cria um objeto do tipo `Account` na memória Heap.

Java Pilha e pilha

A variável de referência ref é criada na pilha dentro do frame para m3.

Java Pilha e pilha

O operador de atribuição faz com que a variável de referência aponte para o objeto no Heap.

Java Pilha e pilha

Assim que o método termina sua execução, o controle retorna ao método que o chamou, que neste caso é o método m2.

Java Pilha e pilha

O quadro para o método m3 é removido da pilha.

Java Pilha e pilha

Como a variável de referência não aponta mais para o objeto no Heap, esse objeto torna-se elegível para coleta de lixo.

Java Pilha e pilha

Assim que o método m2 termina, ele é removido da pilha e todas as suas variáveis ​​ficam indisponíveis. O mesmo acontece com o método m1 e, eventualmente, o controle retorna ao método principal.

E se um objeto mantiver outra referência como sua 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;
}
class B {
    int c;
    int d;
}

Neste caso, a variável de referência `child` reside no Heap como parte do objeto `A`, e por sua vez aponta para seu próprio objeto `B`, conforme mostrado abaixo.

Java Pilha e pilha

Em que consiste a coleta de lixo Java?

Coleta de lixo em Java O coletor de lixo é o processo pelo qual a JVM realiza o gerenciamento de memória automaticamente. Ele encontra objetos que não são mais acessíveis por meio de nenhuma referência ativa e recupera a memória alocada. A alocação dinâmica de memória ocorre através do operador `new`, e a memória permanece alocada até que o programa não mantenha mais nenhuma referência ao objeto.

Quando não restam referências, o objeto é considerado desnecessário e a memória que ele ocupa pode ser liberada. Não há necessidade explícita de destruir um objeto porque Java O coletor de lixo lida com a desalocação automaticamente.

A técnica por trás disso é conhecida como Coleta de lixoProgramas que não liberam memória acabam travando quando não há mais nada para alocar. Diz-se que esses programas têm perdas de memória. Coleta de lixo em Java executa automaticamente ao longo da vida útil do programa, o que elimina o ônus da desalocação manual e reduz o risco de vazamentos.

Em C, por outro lado, o programador é responsável por liberar a memória alocada dinamicamente por meio da função free(). É aqui que... Java O gerenciamento de memória oferece uma grande vantagem.

As JVMs HotSpot modernas incluem vários coletores de lixo otimizados para diferentes cargas de trabalho. O coletor de lixo padrão G1 visa equilibrar a taxa de transferência e os tempos de pausa em heaps de vários gigabytes. O ZGC e o Shenandoah visam pausas de menos de um milissegundo em heaps muito grandes, o que os torna...tracativo para serviços sensíveis à latência. Escolher o coletor certo e ajustar os tamanhos da Geração Jovem, Geração Antiga e Metaespaço é uma habilidade fundamental para Java trabalho de desempenho.

Observação: Todos os objetos são criados na seção Heap da memória, que é a região gerenciada pelo coletor de lixo.

Exemplo: Para aprender o mecanismo de coleta de lixo em Java

Este passo a passo mostra quando as referências se tornam elegíveis para coleta de lixo em um programa simples.

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. Como 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 das linhas 20, 21 e 22. Salve, compile e execute o código.

Passo 4) Conforme ilustrado no diagrama abaixo, duas variáveis ​​de referência agora apontam para o mesmo objeto.

Mecanismo de coleta de lixo

Passo 5) Remova o comentário das linhas 23 e 24. Salve, compile e execute o código.

Passo 6) Conforme mostrado abaixo, s2 torna-se nulo, mas s3 ainda aponta para o objeto, portanto o objeto ainda não está qualificado para coleta de lixo.

 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) Nesse ponto, nenhuma referência aponta para o objeto, então ele se torna elegível para coleta de lixo. O coletor de lixo o remove da memória e não há como recuperá-lo.

 Aprenda coletor de lixo

Como excluir um objeto em Java?

Java Não fornece um operador de exclusão manual, portanto, a abordagem padrão é remover todas as referências ao objeto para que o coletor de lixo possa recuperá-lo.

1) Para tornar um objeto elegível para coleta de lixo, atribua o valor nulo a todas as variáveis ​​de referência que apontam para ele.

2) Os tipos primitivos não são objetos, portanto não podem receber o valor nulo. Seu armazenamento é liberado automaticamente quando o frame da pilha que os envolve é removido.

Como excluir um objeto em Java

Perguntas Frequentes

A pilha armazena frames de métodos, variáveis ​​locais e referências na ordem LIFO (último a entrar, primeiro a sair) por thread. O heap armazena todos os objetos criados com `new` e é compartilhado entre threads, razão pela qual o coletor de lixo o gerencia.

O coletor de lixo percorre as cadeias de referência a partir das raízes do coletor, como threads ativas e campos estáticos. Qualquer objeto que não possa ser alcançado a partir de uma raiz é considerado inalcançável e torna-se elegível para recuperação durante o próximo ciclo de coleta.

A Geração Jovem armazena objetos de curta duração nos espaços Eden e Survivor. A Geração Antiga armazena objetos que sobrevivem a múltiplas coleções. O Metaspace é uma região de memória nativa que armazena metadados de classe e substituiu o antigo PermGen em Java 8.

G1 é o padrão e adequado para a maioria das cargas de trabalho em heaps de vários gigabytes. ZGC e Shenandoah visam pausas de submilissegundos em heaps muito grandes e são boas opções para serviços sensíveis à latência executados em Java 17 ou posterior.

Defina todas as referências que apontam para o objeto como nulas ou deixe que as referências saiam do escopo quando seus frames da pilha forem removidos. Assim que nenhuma referência ativa alcançar o objeto, o coletor de lixo recuperará sua memória heap.

Sim. As ferramentas de otimização baseadas em IA analisam os logs do GC, as taxas de alocação e os histogramas de pausa para recomendar tamanhos de Heap, flags de coletor e proporções da Geração Jovem. Elas encurtam o ciclo de feedback em comparação com a otimização manual, especialmente em cargas de trabalho G1, ZGC e Shenandoah.

Plataformas de observabilidade baseadas em IA ingerem dumps de heap e métricas em tempo real, agrupando então os grafos de objetos retidos para sinalizar classes e cadeias de referência suspeitas. Isso revela candidatos a vazamentos mais rapidamente do que a análise manual de heap e ajuda as equipes a identificar a causa raiz em produção.

Resuma esta postagem com: