关于java:JVM系列之JIT中的Virtual-Call接口

7次阅读

共计 2016 个字符,预计需要花费 6 分钟才能阅读完成。

简介

上一篇文章咱们解说了 Virtual Call 的定义并举例剖析了 Virtual Call 在父类和子类中的优化。

JIT 对类能够进行优化,那么对于 interface 可不可以做同样的优化么?

一起来看看吧。

最罕用的接口 List

List 应该是大家最最罕用的接口了,我想这个大家应该不会反驳。

public interface List<E> extends Collection<E> {

明天咱们就拿 List 来做例子,体验一下 JIT 优化接口的神秘。

还是上代码,要剖析的代码如下:

public class TestVirtualListCall {public static void main(String[] args) throws InterruptedException {List<String> list=new ArrayList<>();
        for (int i = 0; i < 10000; i++)
        {doWithVMethod(list);
        }
        Thread.sleep(1000);
    }

    public static void doWithVMethod(List<String> list)
    {list.add("www.flydean.com");
    }
}

如果在命令行运行,大家记得在运行时增加参数 -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:-Inline

间接看 JIT Watcher 的后果:

咱们能够看到 JIT 中先对 ArrayList 的实现类做了一个比拟。

而后调用的是 invokeinterface,然而其本质还是 invokevirtual, 并且咱们能够看到这个调用是被优化过了:optimized virtual call。

多个 List 的调用

同样的,咱们能够测试一下多个 list 子类的状况下怎么调用:

public class TestVirtualListCall2 {public static void main(String[] args) throws InterruptedException {List<String>[] lists=new List[]{new ArrayList<>(),new LinkedList<>()};
        for (int i = 0; i < 10000; i++)
        {doWithVMethod(lists[i%2]);
        }
        Thread.sleep(1000);
    }

    public static void doWithVMethod(List<String> list)
    {list.add("www.flydean.com");
    }
}

同样,应用 JIT Watcher 来运行:

咱们能够看到 JIT 做了两次对象类型的比拟,而后对两个 invokeinterface 都做了优化。

后果和咱们的父类子类后果是一样的。

不一样的 List 调用

下面咱们在做多个 list 调用的时候,是轮循着来调用的,如果咱们先调用 ArrayList 的办法,再调用 LinkedList 的办法,会有什么不同呢?

一起来看看。

public class TestVirtualListCall3 {public static void main(String[] args) throws InterruptedException {List<String> list1 = new ArrayList<>();
        List<String> list2 = new LinkedList<>();
        for (int i = 0; i < 10000; i++)
        {doWithVMethod(list1);
        }
        Thread.sleep(1000);
        for (int i = 0; i < 10000; i++)
        {doWithVMethod(list2);
        }
        Thread.sleep(1000);
    }

    public static void doWithVMethod(List<String> list)
    {list.add("www.flydean.com");
    }
}

下面咱们先循环 ArrayList,而后再循环 LinkedList。

看下后果有什么不同:

能够看到,JIT 先比拟了 ArrayList, 而后只做了一次办法的优化。

也就是说 LinkedList 的调用是没有进行代码优化的。

下面的后果是在 C2 编译器下,也就是 level4 的编译程度下解析的。

咱们看下如果在 C1 编译器下,也就是 Level3 编译程度下有什么不同。

能够看到 C1 编译下,所有的 invokeinterface 都没有进行编译优化,只有在 C2 编译下,才会进行优化。

不同的 JVM 版本可能优化形式不一样。大家能够自行试验。

总结

本文用实例展现了 Virtual Call 在 interface 下面的优化应用。

感兴趣的敌人,能够一起探讨。

本文作者:flydean 程序那些事

本文链接:http://www.flydean.com/jvm-virtual-call-interface/

本文起源:flydean 的博客

欢送关注我的公众号: 程序那些事,更多精彩等着您!

正文完
 0