Heap em Java:alocação de memória dinâmica
Em Java, o
heap é uma região de memória usada para alocação de memória dinâmica. É onde todos os objetos Java (instâncias de classes) e matrizes são armazenados. Não é * uma estrutura de dados como a estrutura de dados da heap que você pode encontrar nos cursos de algoritmos (min-heap, max-heap). É crucial entender essa distinção.
Características -chave do heap java: 1.
Alocação dinâmica: A memória dos objetos é alocada em tempo de execução, não com tempo de compilação, conforme necessário. Você não predefina o tamanho exato dos objetos de antemão.
2.
Recurso compartilhado: O heap java é um recurso compartilhado em todos os threads dentro de uma JVM. Isso significa que vários threads podem acessar e modificar objetos na pilha. Mecanismos de sincronização (como blocos `sincronizados`, bloqueios etc.) são necessários para gerenciar o acesso simultâneo e impedir a corrupção de dados.
3.
Coleta de lixo: A pilha é gerenciada pelo Java Garbage Collector (GC). O GC recupera automaticamente a memória ocupada por objetos que não são mais acessíveis (ou seja, não mais referenciados por nenhuma parte do programa). Isso elimina a necessidade de gerenciamento de memória manual como `Malloc ()` e `Free ()` em idiomas como C ++.
4.
ciclo de vida do objeto: Os objetos são criados na pilha usando a palavra -chave `new`. Eles residem na pilha até ficar inacessíveis e acabam sendo coletados pelo GC.
5.
tamanho é ajustável: O tamanho da pilha pode ser configurado ao iniciar a Java Virtual Machine (JVM) usando opções de linha de comando como `-xms` (tamanho inicial do heap) e` -xmx` (tamanho máximo de heap).
Como as funções da heap: 1.
Criação de objetos: Quando você cria um novo objeto usando `new`, a JVM aloca memória para o objeto na pilha. Os campos do objeto são inicializados de acordo com a definição de classe.
`` `Java
classe myclass {
int x;
Nome da string;
}
classe pública principal {
public static void main (string [] args) {
Myclass obj =new myclass (); // objeto é criado na pilha
obj.x =10;
obj.name ="exemplo";
}
}
`` `
Neste exemplo, `new myclass ()` aloca memória na pilha para um objeto do tipo 'myclass`. A variável `obj` em` main` é uma * referência * à localização deste objeto na pilha. Não é o objeto em si, mas um ponteiro ou endereço.
2.
Referências de objeto: Os objetos são acessados e manipulados por meio de referências. Várias referências podem apontar para o mesmo objeto na pilha. Se todas as referências a um objeto forem perdidas (torne -se nulo, saia do escopo, etc.), o objeto ficará inacessível.
`` `Java
Myclass obj1 =new myclass ();
MyClass obj2 =obj1; // obj2 agora faz referência ao mesmo objeto que obj1
obj1 =nulo; // Obj1 não faz mais referência ao objeto. Mas o obj2 ainda o faz.
// O objeto MyClass é elegível apenas para a coleta de lixo quando o Obj2 também se torna inacessível.
`` `
3.
Processo de coleta de lixo: *
Análise de acessibilidade: O GC determina quais objetos ainda são alcançáveis, rastreando referências a partir de objetos raiz (por exemplo, variáveis locais em métodos ativos, variáveis estáticas).
*
marcação: Objetos acessíveis são marcados como "vivos".
*
varredura/compactação: Objetos inacessíveis são removidos da pilha. Alguns algoritmos GC também compactam a pilha para reduzir a fragmentação.
4.
Fragmentação de heap: Com o tempo, a pilha pode se fragmentar, o que significa que a memória livre está espalhada em pequenos blocos não contíguos. Isso pode tornar mais difícil alocar objetos grandes. Os algoritmos GC geralmente incluem fases de compactação para consolidar a memória livre.
5.
Estrutura de heap (hipótese geracional): Os GCs modernos geralmente dividem a pilha em gerações baseadas na "hipótese geracional", que afirma que a maioria dos objetos tem vida útil curta. A pilha é normalmente dividida em:
*
Geração jovem: Onde novos objetos são criados. É ainda dividido em:
*
Eden Space: Onde a maioria dos novos objetos é alocada inicialmente.
*
Espaços de sobrevivência (S0, S1): Usado para manter objetos que sobreviveram a pequenos ciclos de GC.
*
geração antiga (geração titular): Objetos que sobreviveram a vários ciclos GC na geração jovem são promovidos para a antiga geração.
*
Geração permanente (Permgen - depreciada em Java 8, substituída pelo Metaspace): Usado para armazenar metadados da classe e outras informações estáticas. (Nota importante:o Permgen foi substituído pelo Metaspace no Java 8 e posterior, que é alocado da memória nativa e não da pilha.)
A abordagem geracional permite que o GC concentre seus esforços na geração jovem, onde a maior parte do lixo é criada.
ajuste de heap: O ajuste do tamanho da pilha pode afetar significativamente o desempenho do aplicativo.
*
muito pequeno: Ciclos GC frequentes, levando à degradação do desempenho e potencialmente "outfMemoryError".
*
muito grande: GC mais uma pausa, impactando a capacidade de resposta.
É importante monitorar a atividade GC e ajustar o tamanho da pilha com base nas necessidades de aplicativos. Ferramentas como JConsole, VisualVM e Profilers podem ajudar com isso.
Diferenças -chave da pilha: *
heap: Usado para alocação dinâmica de objetos. Compartilhado entre threads. Gerenciado por GC.
*
pilha: Usado para armazenar variáveis locais e informações de chamada de método. Específico do thread (cada thread tem sua própria pilha). A memória é alocada e desalocada de maneira LIFO (última entrada, primeiro a sair).
em resumo: O heap java é a região de memória dinâmica onde residem os objetos. Compreender como as funções da heap, incluindo sua estrutura, o papel do coletor de lixo e questões em potencial como a fragmentação, são cruciais para escrever aplicativos Java eficientes e robustos. O dimensionamento de heap e o ajuste do GC adequado são essenciais para otimizar o desempenho. Lembre -se de que é uma área de memória gerenciada pela JVM e * não * uma estrutura de dados de heap.