概述
前几天在一个群里看到一个朋友发了一个demo,说是JDK的bug,昨天在JVM的一个群里又有朋友发了,觉得挺有意思,分享给大家,希望大家升级JDK的版本的时候注意下是否存在这样的代码,如果存在记得立马改过来。
输出比较有意思,在JDK9以前,只输出一个evaluated,但是JDK9以后的版本却会输出两个evaluated,大家可以测试一下。
猜想
看到这个现象,大家都开始猜测了
首先,到底是编译期问题还是运行时问题?这个好验证,我们用JDK8编译的class分别跑在JDK8和JDK10上,看是不是也有类似的现象。
其次,如果是编译期问题,那到底差异在哪里,从结论看,用JDK10编译的字节码,test方法肯定能执行两次。
大家验证下来发现***种情况没发生类似的问题了,那基本确定是第二种情况,那接下来简单分析下。
简单分析
验证字节码,我们都是通过javap去看的,javap -verbose JavacEvalBug,两个版本下我们分别看到下面的字节码
JDK8编译的字节码
其实基本相当于如下的逻辑
JDK10编译的字节码
粗看已经比较明了了,在JDK10编译的字节码里我们确实看到执行了两次test方法,那就和结论比较匹配了。
这个Bug已经有人汇报给Oracle了,https://bugs.openjdk.java.net/browse/JDK-8204322,大家可以关注下进度,点击原文可以进入BUG链接。
思维发散
上面其实都是涉及到了字符串拼接,JDK9以前用的是StringBuilder来拼接的,而JDK9开始使用了invokeDynamic指令,可以动态指定要调用的方法,而不是一开始就编译好的,这个展开来讲就比较长了,有兴趣的可以网上找点资料了解一下,我有时间也可以专门写篇相关的文章,只是感觉对这块有比较大兴趣或者有兴趣一直读下去的的估计不会太多。
改下Demo让你再惊喜一下
如果上面的Demo改一下,把数组变成int数组
此时你再试试?
【本文是51CTO专栏作者李嘉鹏的原创文章,转载请通过微信公众号(你假笨,id:lovestblog)联系作者本人获取授权】