Explicação do Desempenho: o código é executado mais lentamente após o aquecimento

O código abaixo executa exatamente o mesmo cálculo 3 vezes (ele não faz muito: basicamente adicionando todos os números de 1 a 100m). Os dois primeiros blocos são executados aproximadamente 10 vezes mais rápido que o terceiro. Eu executei este programa de teste mais de 10 vezes e os resultados mostram muito pouca variação.

No máximo, eu esperaria que o terceiro bloco fosse executado mais rapidamente (compilação JIT), mas a saída típica é:

35974537
36368455
296471550

Alguém pode explicar o que está acontecendo? (Só para ficar claro, não estou tentando consertar nada aqui, apenas tentando entender melhor o que está acontecendo)

Nota:

nenhum GC é executado durante o programa (monitorado com-XX:+PrintGC)testado com o Oracle JDK versões 1.6.0_30, 1.7.0_02 e 1.7.0_05também testado com os seguintes parâmetros:-XX:+PrintGC -Xms1000m -Xmx1000m -XX:NewSize=900m => mesmo resultadoo bloco é colocado em um loop, todas as corridas são rápidasse o bloco é extraído para um método, todas as execuções são rápidas (se o método é chamado 3 vezes ou em um loop não faz diferença)
public static void main(String... args) {
    //three identical blocks
    {
        long start = System.nanoTime();
        CountByOne c = new CountByOne();
        int sum = 0;
        for (int i = 0; i < 100000000; i++) {
            sum += c.getNext();
        }
        if (sum != c.getSum()) throw new IllegalStateException(); //use sum
        long end = System.nanoTime();
        System.out.println((end - start));
    }
    {
        long start = System.nanoTime();
        CountByOne c = new CountByOne();
        int sum = 0;
        for (int i = 0; i < 100000000; i++) {
            sum += c.getNext();
        }
        if (sum != c.getSum()) throw new IllegalStateException(); //use sum
        long end = System.nanoTime();
        System.out.println((end - start));
    }
    {
        long start = System.nanoTime();
        CountByOne c = new CountByOne();
        int sum = 0;
        for (int i = 0; i < 100000000; i++) {
            sum += c.getNext();
        }
        if (sum != c.getSum()) throw new IllegalStateException(); //use sum
        long end = System.nanoTime();
        System.out.println((end - start));
    }
}

public static class CountByOne {

    private int i = 0;
    private int sum = 0;

    public int getSum() {
        return sum;
    }

    public int getNext() {
        i += 1;
        sum += i;
        return i;
    }
}

questionAnswers(2)

yourAnswerToTheQuestion