我们知道要执行java代码需要编译器将其编译为字节码文件,再由jvm去翻译字节码文件。
其实jvm(HotSpot为例)翻译字节码文件分为两种方式,一种是解释执行,另一种是即时编译(Just-in-Time compilation,JIT)。所谓解释执行就是边翻译为机器码边执行,而即时编译就是先将一个方法中的所有字节码全部编译成机器码之后再执行。
前者的优势在于无需等待编译,而后者的优势在于执行速度更快。在HotSpot中默认采用混合模式,其先解释执行字节码,然后将其中的热点代码(多次执行,循环等)直接编译成机器码,下次就不用再编译了,让其更快速地运行。
但是在生产环境中,为何不都采用即时编译的模式呢?如果服务端的代码改动的频率不高,花点时间去编译,且不是在运行时能够获得更高的效率?
即时编译运行速度确实快,但是全部采用即时编译的话,jvm无法获得程序的运行时信息,这就使得jvm无法对代码进行很好的优化,而如果先执行进行解释执行的话,是真真实实把整个代码都跑了一遍,jvm知道哪里有坑,哪里需要重点关注,jvm会根据代码的执行情况进行更多的优化,而不仅仅是编译为机器码;再者我们的代码其实也符合二八定律,即80%的代码都不用占用虚拟机很多的计算资源,大约为20%,而对于20%的热点代码需要消耗虚拟机80%的计算资源。
编译完的机器码需存储到磁盘上,这也需要占用比较大的存储空间,想想,我们这里很大一部分代码根本就不需要消耗我很多的计算成本的,而需要占用大量的磁盘空间,这样看也是划不来的~