考虑下面两个长度为2的代码片段:
boolean isOK(int i) {
    for (int j = 0; j < filters.length; ++j) {
        if (!filters[j].isOK(i)) {
            return false;
        }
    }
    return true;
}
和
boolean isOK(int i) {
     return filters[0].isOK(i) && filters[1].isOK(i);
}
我认为,经过充分的预热后,这两块琴的性能应该相似。
我已经使用JMH微基准测试框架对此进行了检查,如此处和此处所述,并观察到第二个片段的运行速度提高了10%以上。
问题:为什么Java没有使用基本循环展开技术优化我的第一个代码段? 
特别是,我想了解以下内容:
- 我可以很容易地产生一个代码,为2个滤波器的情况下最佳的,仍然可以在过滤器另一个号码的情况下工作(想象一个简单的建造者): 
return (filters.length) == 2 ? new FilterChain2(filters) : new FilterChain1(filters)。JITC可以这样做吗?如果不能,为什么? - JITC是否可以检测到'filters.length == 2 '是最常见的情况,并在预热后产生最适合该情况的代码?这应该几乎与手动展开的版本一样最佳。
 - JITC是否可以检测到某个特定实例被非常频繁地使用,然后为该特定实例生成代码(对于该实例,它知道过滤器的数量始终为2)?
更新:得到一个答案,即JITC仅在班级上工作。好的,我知道了。 
理想情况下,我想从对JITC的工作有深刻理解的人那里得到答案。 
基准运行细节:
- 在最新版本的Java 8 OpenJDK和Oracle HotSpot上进行了尝试,结果相似
 - 使用的Java标志:-Xmx4g -Xms4g -server -Xbatch -XX:CICompilerCount = 2(也获得了类似的结果,但没有花哨的标志)
 - 顺便说一句,如果我简单地在一个循环中运行数十亿次(而不是通过JMH),我将获得类似的运行时比率,即第二个片段总是明显更快
 
典型基准输出:
基准(filterIndex)模式Cnt得分错误单位
LoopUnrollingBenchmark.runBenchmark 0 avgt 400 44.202±0.224 ns / op
LoopUnrollingBenchmark.runBenchmark 1 avgt 400 38.347±0.063 ns / op
(第一行对应第一个代码段,第二行对应第二个代码段。
完整的基准代码:
public class LoopUnrollingBenchmark {
    @State(Scope.Benchmark)
    public static class BenchmarkData {
        public Filter[] filters;
        @Param({"0", "1"})
        public int filterIndex;
        public int num;
        @Setup(Level.Invocation) //similar ratio with Level.TRIAL
        public void setUp() {
            filters = new Filter[]{new FilterChain1(), new FilterChain2()};
            num = new Random().nextInt();
        }
    }
    @Benchmark
    @Fork(warmups = 5, value = 20)
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.NANOSECONDS)
    public int runBenchmark(BenchmarkData data) {
        Filter filter = data.filters[data.filterIndex];
        int sum = 0;
        int num = data.num;
        if (filter.isOK(num)) {
            ++sum;
        }
        if (filter.isOK(num + 1)) {
            ++sum;
        }
        if (filter.isOK(num - 1)) {
            ++sum;
        }
        if (filter.isOK(num * 2)) {
            ++sum;
        }
        if (filter.isOK(num * 3)) {
            ++sum;
        }
        if (filter.isOK(num * 5)) {
            ++sum;
        }
        return sum;
    }
    interface Filter {
        boolean isOK(int i);
    }
    static class Filter1 implements Filter {
        @Override
        public boolean isOK(int i) {
            return i % 3 == 1;
        }
    }
    static class Filter2 implements Filter {
        @Override
        public boolean isOK(int i) {
            return i % 7 == 3;
        }
    }
    static class FilterChain1 implements Filter {
        final Filter[] filters = createLeafFilters();
        @Override
        public boolean isOK(int i) {
            for (int j = 0; j < filters.length; ++j) {
                if (!filters[j].isOK(i)) {
                    return false;
                }
            }
            return true;
        }
    }
    static class FilterChain2 implements Filter {
        final Filter[] filters = createLeafFilters();
        @Override
        public boolean isOK(int i) {
            return filters[0].isOK(i) && filters[1].isOK(i);
        }
    }
    private static Filter[] createLeafFilters() {
        Filter[] filters = new Filter[2];
        filters[0] = new Filter1();
        filters[1] = new Filter2();
        return filters;
    }
    public static void main(String[] args) throws Exception {
        org.openjdk.jmh.Main.main(args);
    }
}
          @Setup(Level.Invocation):不确定是否有帮助(请参阅javadoc)。
                final,但是JIT并未看到该类的所有实例都将获得一个长度为2的数组。要看到这一点,它必须深入到createLeafFilters()方法并深入分析代码,以了解该数组将始终为2长。您为什么认为JIT优化器会深入研究您的代码?