Evitando eliminação de código morto
Blackhole e estado.
Evitando eliminação de código morto é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.
Evitando a eliminação de código morto
A maior armadilha das microavaliações de desempenho é a eliminação de código morto (DCE): se o JIT provar que um resultado nunca é usado, ele excluirá o cálculo. Sua avaliação de desempenho não medirá nada. O JMH oferece duas ferramentas para impedir isso — retornar valores e o Blackhole.
A armadilha do DCE
Este laço calcula uma raiz quadrada um milhão de vezes, mas nunca usa o resultado. Um compilador inteligente pode excluir o laço inteiro.
public class Main {
public static void main(String[] args) {
long t = System.nanoTime();
for (int i = 0; i < 1_000_000; i++) {
double ignored = Math.sqrt(i); // result thrown away
}
System.out.println("ns: " + (System.nanoTime() - t));
}
}Correção 1: retorne o resultado
A defesa mais simples é retornar o valor calculado do método @Benchmark. O JMH consome todos os valores retornados, portanto a JVM não pode provar que eles não são usados.
import org.openjdk.jmh.annotations.Benchmark;
public class Bench {
@Benchmark
public double sqrt() {
return Math.sqrt(42.0); // returned -> consumed by JMH
}
}Correção 2: o buraco negro
Quando uma avaliação de desempenho produz vários valores ou você não pode retornar um deles, injete um Blackhole e chame consume(...). O buraco negro convence o JIT de que cada valor é usado, sem o custo de um trabalho real.
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.infra.Blackhole;
public class Bench {
@Benchmark
public void manyValues(Blackhole bh) {
for (int i = 0; i < 100; i++) {
bh.consume(Math.sqrt(i));
}
}
}Objetos @State
Uma classe @State armazena entradas opacas para o otimizador, impedindo a avaliação antecipada de constantes. O JMH a instancia e a passa para sua avaliação de desempenho. O escopo pode ser Thread, Benchmark (compartilhado) ou Group.
import org.openjdk.jmh.annotations.*;
public class Bench {
@State(Scope.Thread)
public static class Data {
public int x = 21;
}
@Benchmark
public int multiply(Data d) {
return d.x * 2; // d.x is not a compile-time constant
}
}@Setup e @TearDown
Dentro de uma classe @State, os métodos anotados com @Setup são executados antes da medição, e @TearDown, depois. Level controla a frequência: Trial (uma vez), Iteration ou Invocation.
import org.openjdk.jmh.annotations.*;
@State(Scope.Thread)
public class Data {
int[] arr;
@Setup(Level.Trial)
public void init() {
arr = new int[1000];
for (int i = 0; i < arr.length; i++) arr[i] = i;
}
}Evite entradas constantes
Nunca forneça constantes literais ao método em teste. Math.sqrt(2.0) pode ser reduzido a uma constante; Math.sqrt(state.value) não pode. Sempre obtenha as entradas de um campo de @State.
Retorno de vários valores
Se o seu teste de desempenho produzir naturalmente dois resultados, você poderá retornar um e consumir o outro por meio de um Blackhole, ou combiná-los. Deixar qualquer um deles sem ser consumido reabre a brecha para DCE.
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.infra.Blackhole;
public class Bench {
@Benchmark
public int twoResults(Blackhole bh) {
int a = 3 * 7;
int b = 5 + 9;
bh.consume(b);
return a;
}
}Custo do Blackhole
O Blackhole foi projetado para ser extremamente barato e também resistente à otimização, mas não é totalmente gratuito. Para operações ultrarrápidas, prefira retornar um único valor; reserve o Blackhole para laços e casos com vários valores.
Verifique a plausibilidade dos números
Se um teste de desempenho informar um tempo impossivelmente baixo (inferior a um nanossegundo para um trabalho real), suspeite de DCE ou de dobramento de constantes. Verifique novamente se os resultados são retornados ou consumidos e se as entradas vêm de @State.
Juntando tudo
Um teste de desempenho robusto lê as entradas de um objeto @State, realiza o trabalho e retorna o resultado com return ou o consome com Blackhole.consume. Com esses três hábitos, DCE e o dobramento de constantes não podem distorcer suas medições.
Verificação rápida
Teste sua compreensão sobre como impedir a eliminação de código morto.
Recapitulação
Você aprendeu a manter os testes de desempenho confiáveis:
- Eliminação de código morto exclui computações não utilizadas.
- Retorne um único resultado para que JMH o consuma.
- Use Blackhole.consume para laços e vários valores.
- Objetos @State mantêm as entradas opacas, impedindo o dobramento de constantes.
- @Setup / @TearDown preparam e limpam o estado no nível escolhido.
Perguntas Frequentes
A aula “Evitando eliminação de código morto” é grátis?
Sim — o texto completo de “Evitando eliminação de código morto” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.
O que vou aprender em “Evitando eliminação de código morto”?
Blackhole e estado. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Java Academy?
Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Evitando eliminação de código morto”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Java Academy?
Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Por que usar JMH
- Escrevendo um benchmark
- Aquecimento e iterações
- Evitando eliminação de código morto