0Pricing
Java Academy · Aula

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

  1. Por que usar JMH
  2. Escrevendo um benchmark
  3. Aquecimento e iterações
  4. Evitando eliminação de código morto
← Voltar para Java Academy