Se você programa em Java, provavelmente já escreveu algo assim milhares de vezes:
var user = new User();
Parece simples: criamos um objeto e ele ocupa na memória apenas o espaço necessário para guardar seus dados.
Mas não é bem assim.
Todo objeto tem uma pequena "mochila"
Além dos dados que você colocou nele, cada objeto Java carrega algumas informações extras usadas internamente pela JVM.
É o chamado Object Header.
Pensa nele como uma pequena etiqueta presa a cada objeto dizendo coisas como:
- qual é o tipo daquele objeto;
- informações usadas pelo Garbage Collector;
- dados usados em locks e
synchronized; - informações internas necessárias para a JVM gerenciá-lo.
Você normalmente nunca vê essa etiqueta.
Mas ela ocupa memória.
Em uma JVM HotSpot de 64 bits, esse cabeçalho tradicionalmente ocupa 12 ou 16 bytes, dependendo da configuração.
Pode parecer pouco.
O problema aparece quando temos milhões de objetos.
Imagine uma aplicação que cria 10 milhões de pequenos objetos.
Economizar apenas 4 bytes por objeto já significaria aproximadamente:
10.000.000 × 4 bytes
≈ 40 MB
E isso é apenas o cabeçalho.
Entra o Project Lilliput
O OpenJDK possui uma iniciativa chamada Project Lilliput, cuja ideia é diminuir o tamanho dessas estruturas internas da JVM.
Uma das principais mudanças é justamente reduzir o Object Header para 64 bits, ou 8 bytes.
Em vez de manter determinadas informações separadas, a JVM passa a compactá-las dentro de uma estrutura menor.
Simplificando:
Antes
[ Object Header ][ dados do objeto ]
12–16 bytes
Compact Object Headers
[ Header ][ dados do objeto ]
8 bytes
Individualmente parece uma diferença pequena.
Em milhões de objetos, deixa de ser pequena.
E por que isso pode deixar Java mais rápido?
Menos memória não significa apenas gastar menos RAM.
Objetos menores também ficam mais próximos uns dos outros na memória.
Isso pode melhorar o uso dos caches da CPU e reduzir a quantidade de trabalho feita pelo Garbage Collector.
Nos testes citados pelo próprio OpenJDK, houve cenários com 22% menos uso de heap, 8% menos CPU e até 15% menos ciclos de Garbage Collection. Os ganhos dependem bastante da aplicação.
E talvez a parte mais interessante seja:
o desenvolvedor não precisa reescrever suas classes para obter esse benefício.
É uma otimização feita dentro da própria JVM.
Quando isso chegou ao Java?
O caminho está sendo gradual:
Java 24 — JEP 450
Compact Object Headers apareceu como recurso experimental.
Java 25 — JEP 519
O recurso deixou de ser experimental e virou uma feature oficial da HotSpot, embora continue desabilitado por padrão.
O próximo passo estudado pelo OpenJDK é justamente torná-lo o layout padrão de objetos.
Esse trabalho já existe como a proposta “Compact Object Headers by Default”, mas, no momento, ela ainda está em Draft.
O mais interessante dessa história
Quando pensamos em otimização, normalmente imaginamos mudar algoritmos, reduzir alocações ou reescrever partes do código.
O Project Lilliput mostra outro lado da evolução do Java:
às vezes milhões de aplicações podem consumir menos memória simplesmente porque a JVM ficou melhor em organizar alguns bits.
Uma mudança de poucos bytes.
Multiplicada por milhões de objetos.
E é aí que poucos bytes deixam de ser poucos.
Referências
- Project Lilliput — OpenJDK
- JEP 450 — Compact Object Headers (Experimental)
- JEP 519 — Compact Object Headers
- OpenJDK — Compact Object Headers by Default
Top comments (0)