In the following code snippet, `Foo1` is a class that increments a counter every time the method `bar()` is called. `Foo2` does the same thing but with one additional level of indirection.

I would expect `Foo1` to be faster than `Foo2`, however in practice, `Foo2` is consistently 40% faster than `Foo1`. How is the JVM optimizing the code such that `Foo2` runs faster than `Foo1`?

### Some Details

* The test was executed with `java -server CompositionTest`.
* Running the test with `java -client CompositionTest` produces the expected results, that `Foo2` is slower than `Foo1`.
* Switching the order of the loops does not make a difference.
* The results were verified with java6 on both sun and openjdk's JVMs.

### The Code

```
public class CompositionTest {

    private static interface DoesBar {
        public void bar();
        public int count();
        public void count(int c);
    }

    private static final class Foo1 implements DoesBar {
        private int count = 0;
        public final void bar() { ++count; }
        public int count() { return count; }
        public void count(int c) { count = c; }
    }

    private static final class Foo2 implements DoesBar {
        private DoesBar bar;
        public Foo2(DoesBar bar) { this.bar = bar; }
        public final void bar() { bar.bar(); }
        public int count() { return bar.count(); }
        public void count(int c) { bar.count(c); }
    }

    public static void main(String[] args) {
        long time = 0;
        DoesBar bar = null;
        int reps = 100000000;

        for (int loop = 0; loop < 10; loop++) {
            bar = new Foo1();
            bar.count(0);

            int i = reps;
            time = System.nanoTime();
            while (i-- > 0) bar.bar();
            time = System.nanoTime() - time;

            if (reps != bar.count())
                throw new Error("reps != bar.count()");
        }
        System.out.println("Foo1 time: " + time);

        for (int loop = 0; loop < 10; loop++) {
            bar = new Foo2(new Foo1());
            bar.count(0);

            int i = reps;
            time = System.nanoTime();
            while (i-- > 0) bar.bar();
            time = System.nanoTime() - time;

            if (reps != bar.count())
                throw new Error("reps != bar.count()");
        }
        System.out.println("Foo2 time: " + time);
    }
}

```