简介

上一篇文章咱们解说了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的博客

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