如何在现代JVM实现中实现instanceof?

gex*_*ide 2 java implementation jvm instanceof

由于在其他线程中完成了基准测试(参见/sf/answers/27833221/),因此可以看出Java 6中的instanceof实际上非常快.这是如何实现的?

我知道对于单继承,最快的想法是使用一些嵌套间隔编码,其中每个类维持[低,高]间隔,而instanceof只是间隔包含测试,即2个整数比较.但它是如何制作接口的(因为区间包含仅适用于单继承)?如何处理类加载?加载新的子类意味着必须调整很多间隔.

Pet*_*rey 5

AFAIK每个类都知道它扩展的所有类和它实现的接口.这些可以存储在散列集中,给出O(1)查找时间.

当代码经常采用相同的分支时,成本可以几乎消除,因为CPU可以在确定是否应该使分支成本接近于零之前执行分支中的代码.

由于4年前进行了微基准测试,我预计最新的CPU和JVM会更快.

public static void main(String... args) {
    Object[] doubles = new Object[100000];
    Arrays.fill(doubles, 0.0);
    doubles[100] = null;
    doubles[1000] = null;
    for (int i = 0; i < 6; i++) {
        testSameClass(doubles);
        testSuperClass(doubles);
        testInterface(doubles);
    }
}

private static int testSameClass(Object[] doubles) {
    long start = System.nanoTime();
    int count = 0;
    for (Object d : doubles) {
        if (d instanceof Double)
            count++;
    }
    long time = System.nanoTime() - start;
    System.out.printf("instanceof Double took an average of %.1f ns%n", 1.0 * time / doubles.length);
    return count;
}

private static int testSuperClass(Object[] doubles) {
    long start = System.nanoTime();
    int count = 0;
    for (Object d : doubles) {
        if (d instanceof Number)
            count++;
    }
    long time = System.nanoTime() - start;
    System.out.printf("instanceof Number took an average of %.1f ns%n", 1.0 * time / doubles.length);
    return count;
}

private static int testInterface(Object[] doubles) {
    long start = System.nanoTime();
    int count = 0;
    for (Object d : doubles) {
        if (d instanceof Serializable)
            count++;
    }
    long time = System.nanoTime() - start;
    System.out.printf("instanceof Serializable took an average of %.1f ns%n", 1.0 * time / doubles.length);
    return count;
}
Run Code Online (Sandbox Code Playgroud)

终于打印了

instanceof Double took an average of 1.3 ns
instanceof Number took an average of 1.3 ns
instanceof Serializable took an average of 1.3 ns
Run Code Online (Sandbox Code Playgroud)

如果我改变"双打"

    for(int i=0;i<doubles.length;i+=2)
        doubles[i] = "";
Run Code Online (Sandbox Code Playgroud)

我明白了

instanceof Double took an average of 1.3 ns
instanceof Number took an average of 1.6 ns
instanceof Serializable took an average of 2.2 ns
Run Code Online (Sandbox Code Playgroud)

注意:如果我改变了

if (d instanceof Double)
Run Code Online (Sandbox Code Playgroud)

if (d != null && d.getClass() == Double.class)
Run Code Online (Sandbox Code Playgroud)

表现是一样的.