hello,小伙伴们好,我是江湖人送外号[道格牙]的子牙老师。
前几次的文章都比较烧脑,今天咱们来个简单点的。咱们把++给讲透彻。别看简单,面试中遇到,与面试官谁胜谁负还真不好说呢:
1、byte++与int++,哪段代码性能更高?为什么?
2、++在前与++在后,为什么结果不同?
3、--又是如何实现的?在前在后为什么结果不同?
4、++、--操作的局限听说过吗?
将这些问题讲明白后,我再给大家讲讲++、--对应的字节码指令。帮大家武装到牙齿,从容与面试官斗智斗勇,不落下风,获得局部好感!面试官内心戏:这小伙子我降不住啊。(面试官挺不容易的,每个人都想虐。^_^)
比比谁跑得快
如果面试官把下面两段代码摆在你的面前,问你哪段代码性能更高。你会不会心里一万匹草泥马在奔腾:玩我呢!这有差别吗?^_^
讲真,面试官没玩你。这两段代码的性能是完全不一样的。上字节码
结果显而易见了吧:int++只对应一句字节码指令,而byte++对应了五句字节码指令。如果不抬杠的话,性能是五倍的差异。这就是细节!
减减操作
与++操作对应的是--操作。如果你来实现,你会新增一个字节码指令吗?但是JVM没有,依然是用iinc指令来实现的。怎么实现的呢?看下面公式
i - 1 = i + (-1)
减一个数是不是等于加上这个数的负数。JVM也是这样设计的,这样就节省了一个字节码指令位置。其实JVM的字节码指令位置是很紧张的。为什么这么说呢?因为一个字节码指令设计的时候只给了一个字节,一个字节,无符号的话,最大是255。言外之意,JVM的字节码指令最多只又255个,现在已经用了202个了。
Intel CPU是怎么解决指令集不够用的问题的呢?最开始其实也只有一个字节,后面扩展成二级指令,现在已经到三级指令了。所以其实你的知识面越底层,真正的理解底层,你就能预测出未来可能到来的变化:比如这里说的,JVM当前的一级指令不够用了,它也要引入二级指令。这就是阿里P8级的硬要求之一:技术前瞻性。
iinc指令
不管是++操作还是--操作,编译后对应的字节码指令都是iinc指令。相信讲下这个指令,看图
大概讲一下
1、对应的是字节码指令
2、对应的是这个指令作用的局部变量在局部变量表中的索引
3、一次加多少。固定值1。如果这个值不存在特殊考虑,我觉得这个字节可以节省下来。后面会不会这样做呢?拭目以待
可能有小伙伴马上就要问了:既然只是一句字节码指令,为什么不是原子操作呢?继续上图
因为iinc指令,对应的hotspot源码,至少要做这么多事情。hotspot这里的代码是不会加锁的,所以这个操作不是线程安全的。
这个代码是不是大家一看就看懂了。这段代码是截取自我手写的JVM项目。这就是手写JVM对于每个人的意义:你自己写,你就得站在设计者的角度去思考,你就会不自觉的把问题越想越细致。而且,你手上有一个自己可以为所欲为的JVM,你的所有想法都可以付诸实践。
超级加倍
讲到这里不知道大家有没有发现一个问题哦。iinc指令的第一个参数,即代表slot index这个参数,只有一个字节。这就是++、--存在的约束。这个约束就是如果局部变量的索引超过128,就只能走byte++那种复杂的逻辑。这能忍?是可忍熟不可忍?JVM怎么做的呢?指令拓宽!什么意思呢?看图
到这里就把iinc指令超级无敌透彻得讲明白了,小伙伴们看得嗨不嗨,应该是嗨了。那子牙老师厚颜无耻地要一波点赞转发不过分吧。^_^
结语
我是子牙老师,喜欢钻研底层,深入研究Windows、Linux内核、JVM。喜欢分享硬核知识,如果你也喜欢研究底层,喜欢硬核知识,关注我。