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.

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:
- montão
- CorMonitor
- Code
- 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.
A variável x em m1 também é criada no frame de m1 na pilha, como mostrado na imagem abaixo.
O método m1 chama então o método m2. Na pilha, um novo frame é criado para m2 acima do frame de m1.
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.
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.
A variável de referência ref é criada na pilha dentro do frame para m3.
O operador de atribuição faz com que a variável de referência aponte para o objeto no Heap.
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.
O quadro para o método m3 é removido da 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.
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.
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.
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.
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.
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.
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.


















