Pilha de memória e espaço de heap em Java
1. Introdução
Para executar um aplicativo da maneira ideal, a JVM divide a memória em pilha e pilha de memória. Whenever we declare new variables and objects, call new method, declare a String or perform similar operations, JVM designates memory to these operations from either Stack Memory or Heap Space.
Neste tutorial, discutiremos esses modelos de memória. Vamos listar algumas diferenças importantes entre eles, como são armazenados na RAM, os recursos que oferecem e onde usá-los.
2. Pilha de memória em Java
Stack Memory in Java is used for static memory allocation and the execution of a thread. Contém valores primitivos que são específicos de um método e referências a objetos que estão em um heap, referidos a partir do método.
O acesso a esta memória está na ordem LIFO (Last-In-First-Out). Sempre que um novo método é chamado, é criado um novo bloco no topo da pilha, que contém valores específicos para esse método, como variáveis primitivas e referências a objetos.
Quando o método termina a execução, o quadro de pilha correspondente é liberado, o fluxo retorna ao método de chamada e o espaço fica disponível para o próximo método.
2.1. Principais recursos da pilha de memória
Além do que discutimos até agora, a seguir estão alguns outros recursos da memória da pilha:
-
Ele cresce e diminui à medida que novos métodos são chamados e retornados, respectivamente
-
Variáveis dentro da pilha existem apenas enquanto o método que as criou estiver em execução
-
É automaticamente alocado e desalocado quando o método termina a execução
-
Se esta memória estiver cheia, o Java lançajava.lang.StackOverFlowError
-
O acesso a essa memória é rápido quando comparado à memória heap
-
Essa memória é segura para threads, pois cada thread opera em sua própria pilha
3. Heap Space em Java
Heap space in Java is used for dynamic memory allocation for Java objects and JRE classes at the runtime. Novos objetos sempre são criados no espaço de heap e as referências a esses objetos são armazenadas na memória da pilha.
Esses objetos têm acesso global e podem ser acessados de qualquer lugar no aplicativo.
Esse modelo de memória é dividido em partes menores chamadas gerações, são elas:
-
Young Generation – é onde todos os novos objetos são alocados e envelhecidos. Uma pequena coleta de lixo ocorre quando isso é preenchido
-
Old or Tenured Generation – é onde os objetos que sobrevivem há muito tempo são armazenados. Quando os objetos são armazenados na Geração Jovem, um limite para a idade do objeto é definido e quando esse limite é atingido, o objeto é movido para a geração anterior
-
Permanent Generation – consiste em metadados JVM para as classes de tempo de execução e métodos de aplicativo
Essas diferentes partes também são discutidas neste artigo -Difference Between JVM, JRE, and JDK.
Sempre podemos manipular o tamanho da memória heap conforme nossos requisitos. Para obter mais informações, visite estelinked example article.
3.1. Principais recursos do Java Heap Memory
Além do que discutimos até agora, a seguir estão alguns outros recursos do espaço de heap:
-
É acessado por meio de técnicas complexas de gerenciamento de memória que incluem Geração Jovem, Geração Antiga ou Tenured e Geração Permanente
-
Se o espaço de heap estiver cheio, Java lançajava.lang.OutOfMemoryError
-
O acesso a esta memória é relativamente mais lento que a memória da pilha
-
Essa memória, em contraste com a pilha, não é desalocada automaticamente. Ele precisa do Garbage Collector para liberar objetos não utilizados, a fim de manter a eficiência do uso da memória
-
Ao contrário da pilha, um heap não é thread-safe e precisa ser protegido por meio da sincronização adequada do código
4. Exemplo
Com base no que aprendemos até agora, vamos analisar um código Java simples e avaliar como a memória é gerenciada aqui:
class Person {
int pid;
String name;
// constructor, setters/getters
}
public class Driver {
public static void main(String[] args) {
int id = 23;
String pName = "Jon";
Person p = null;
p = new Person(id, pName);
}
}
Vamos analisar isso passo a passo:
-
Ao entrar no métodomain(), um espaço na memória da pilha seria criado para armazenar primitivas e referências deste método
-
O valor primitivo do inteiroid será armazenado diretamente na memória da pilha
-
A variável de referênciap of typePerson will também será criada na memória da pilha, que apontará para o objeto real no heap
-
-
A chamada para o construtor parametrizadoPerson(int, String) demain() alocará mais memória no topo da pilha anterior. Isso armazenará:
-
A referência de objetothis do objeto de chamada na memória da pilha
-
O valor primitivoid da pilha de memória
-
A variável de referência do argumentoStringpersonName que apontará para a string real do pool de strings na memória heap
-
-
Este construtor padrão está chamando o métodosetPersonName(), para o qual a alocação adicional ocorrerá na memória da pilha em cima do anterior. Isso armazenará novamente as variáveis da maneira descrita acima.
-
No entanto, para o objeto recém-criadop of typePerson, todas as variáveis de instância serão armazenadas na memória heap.
Essa alocação é explicada neste diagrama:
5. Sumário
Antes de concluirmos este artigo, vamos resumir rapidamente as diferenças entre a Stack Memory e o Heap Space:
Parâmetro | Pilha de memória | Espaço de pilha |
---|---|---|
Inscrição |
Stack é usado em partes, uma de cada vez durante a execução de um thread |
Todo o aplicativo usa o espaço Heap durante o tempo de execução |
Size |
A pilha tem limites de tamanho dependendo do sistema operacional e geralmente é menor que o Heap |
Não há limite de tamanho para Heap |
Armazenamento |
Armazena apenas variáveis primitivas e referências a objetos que são criados no Heap Space |
Todos os objetos recém-criados são armazenados aqui |
Ordem |
Ele é acessado usando o sistema de alocação de memória Last-in First-out (LIFO) |
Essa memória é acessada por meio de técnicas complexas de gerenciamento de memória que incluem Geração Jovem, Geração Antiga ou Tenured e Geração Permanente. |
Life |
A pilha de memória só existe enquanto o método atual estiver em execução |
O espaço de heap existe enquanto o aplicativo é executado |
Eficiência |
Comparativamente muito mais rápido para alocar quando comparado ao heap |
Mais lento para alocar quando comparado à pilha |
Allocation/Deallocation |
Esta memória é automaticamente alocada e desalocada quando um método é chamado e retornado respectivamente |
O espaço de heap é alocado quando novos objetos são criados e desalocados pelo Gargabe Collector quando eles não são mais referenciados |
6. Conclusão
Pilha e pilha são duas maneiras pelas quais o Java aloca memória. Neste artigo, entendemos como eles funcionam e quando usá-los para desenvolver melhores programas Java.
Para aprender mais sobre Gerenciamento de Memória em Java, dê uma olhada emthis article here. Também discutimos o Coletor de lixo JVM, que é discutido brevementeover in this article.