JVM: A Máquina Virtual Java - Fundamentos e Funcionamento

Published: (December 14, 2025 at 03:54 PM EST)
4 min read
Source: Dev.to

Source: Dev.to

Visão geral da JVM

A JVM executa programas Java compilados em bytecode, funcionando como uma camada de abstração entre o código Java e o sistema operacional/hardware. Ela não é apenas um interpretador; é uma especificação completa que define a execução do bytecode, o gerenciamento de memória, o funcionamento de threads e outros aspectos críticos.

Arquitetura da JVM

A arquitetura pode ser dividida em três componentes principais:

Class Loader

  • Responsabilidades: Carregar arquivos .class na memória da JVM.
  • Fases:
    1. Carregamento: Localiza e lê o arquivo .class, criando sua representação binária.
    2. Linkagem: Verifica a correção do bytecode, prepara estruturas para campos estáticos e resolve referências simbólicas.
    3. Inicialização: Executa construtores estáticos e inicializa variáveis estáticas.
  • Hierarquia:
    • Bootstrap ClassLoader: Carrega classes do núcleo do Java.
    • Extension ClassLoader: Carrega extensões da plataforma.
    • Application ClassLoader: Carrega classes da aplicação.

Essa hierarquia garante isolamento e segurança ao carregar classes.

Áreas de memória

ÁreaDescrição
HeapAloca todos os objetos. Compartilhada entre threads. Gerenciada pelo Garbage Collector (GC). Dividida em gerações (Young, Old).
Method AreaArmazena metadados de classes, constantes de tempo de execução, código de métodos e construtores. Compartilhada entre threads.
StackUma pilha por thread, contendo frames de método (variáveis locais, operandos, informações de execução). Operação LIFO.
Program Counter (PC) RegisterMantém o endereço da instrução JVM atual. Cada thread tem seu próprio PC.
Native Method StackArmazena informações de métodos nativos (C/C++) acessados via Java Native Interface (JNI).
Metaspace (a partir do Java 8)Guarda metadados de classes; não faz parte da heap gerenciada.

Execution Engine

  • Interpretador: Lê e executa instruções de bytecode uma a uma. Simples, porém mais lento.
  • JIT Compiler (Just‑In‑Time): Compila bytecode “quente” (hot spots) em código de máquina nativo, armazenando‑o em cache para execuções subsequentes. Usa otimizações como inlining, eliminação de código morto e otimizações específicas de processador.
  • Garbage Collector: Gerencia automaticamente a memória, removendo objetos não mais referenciados.

Fluxo de execução de um programa Java

  1. Compilação: O código‑fonte .java é compilado pelo javac em bytecode (.class), independente de plataforma.
  2. Inicialização da JVM: O Class Loader carrega as classes necessárias, começando pela classe que contém o método main. O carregamento é lazy (sob demanda).
  3. Interpretação e compilação JIT: O bytecode é inicialmente interpretado; o JIT monitora a frequência de execução e compila hot spots em código nativo, armazenando‑os em cache.
  4. Coleta de lixo: O GC monitora a heap, identifica objetos inacessíveis e libera sua memória automaticamente.

Garbage Collection (GC)

O GC identifica objetos alcançáveis a partir de GC roots (variáveis locais nas stacks, campos estáticos, referências JNI) e marca todos os objetos acessíveis. Objetos não marcados são considerados lixo e podem ser removidos.

Gerações da heap

  • Young Generation: Onde novos objetos são alocados. Subdividida em Eden (criação inicial) e dois Survivor Spaces. Quando Eden enche, ocorre um Minor GC que move objetos sobreviventes para Survivor.
  • Old Generation: Contém objetos que sobreviveram a vários ciclos de GC na Young Generation. Coletas aqui (Major ou Full GC) são menos frequentes, porém mais custosas.
  • Metaspace: Armazena metadados de classes (substituiu a Permanent Generation a partir do Java 8) e não faz parte da heap gerenciada.

Coletores de lixo disponíveis

ColetorCaracterísticas
Serial GCUsa uma única thread; adequado para aplicações pequenas com heaps de poucos megabytes.
Parallel GCUtiliza múltiplas threads; maximiza throughput, mas pode causar pausas perceptíveis. Padrão em muitas versões da JVM.
CMS (Concurrent Mark Sweep)Executa a maior parte da coleta concorrentemente com a aplicação, reduzindo pausas. Descontinuado em versões recentes.
G1 GC (Garbage First)Divide a heap em regiões e coleta prioritariamente as regiões mais “sujas”. Oferece pausas previsíveis; padrão desde o Java 9.
ZGC e ShenandoahColetores de baixa latência que mantêm pausas abaixo de 10 ms mesmo com heaps de terabytes, usando técnicas avançadas de coloração de ponteiros e compactação concorrente.

JIT Compiler e compilação em camadas

A JVM moderna emprega tiered compilation, combinando interpretação com dois níveis de compilação JIT:

  • C1 Compiler: Compila rapidamente com otimizações básicas, ideal para código executado poucas vezes ou durante a inicialização.
  • C2 Compiler: Realiza otimizações agressivas, porém leva mais tempo; usado para hot spots que são executados muitas vezes.

Otimizações do JIT

  • Inlining: Substitui chamadas de método pelo corpo do método, eliminando overhead e permitindo otimizações adicionais.
  • Escape Analysis: Determina se objetos podem ser alocados na stack ao invés da heap, reduzindo a pressão sobre o GC.
  • Loop Unrolling: Desenrola loops para diminuir o número de iterações de controle.
  • Dead Code Elimination: Remove código que nunca será executado.
  • Other advanced optimizations: Profile‑guided optimizations, speculative optimizations, and runtime de‑optimization when assumptions change.

Esta visão geral cobre os principais componentes e mecanismos da JVM, oferecendo uma base sólida para entender como o bytecode Java é executado, otimizado e gerenciado em tempo de execução.

Back to Blog

Related posts

Read more »

History of Java

Origins Java was started in 1991 by James Gosling as part of a research initiative called the Green Project. The main objective of this project was to create a...

Method overriding in Java

What is method overriding When a subclass provides a specific implementation for a method that is already defined in its parent class, it is called method over...

java 8 (Stream API)

Features of Stream API - Declarative – Write concise and readable code using functional style. - Lazy Evaluation – Operations are executed only when a terminal...