JVM的多样性与Java平台的独立性
所有的JVM实现都有一个共同点 , 即它们都试图将应用程序的字节码转换为本地机器指令 。一些JVM在载入应用程序后会解释执行应用程序 , 同时使用性能计数器来查找“热点”代码 。还有一些JVM会调用解释执行的阶段 , 直接编译运行 。资源密集型编译任务对应用程序来说可能会产生较大影响 , 尤其是那些客户端模式下运行的应用程序 , 但是资源密集型编译任务可以执行一些比较高级的优化任务 。更多相关内容请参见相关资源
如果你是Java初学者 , JVM本身错综复杂结构会让你晕头转向的 。不过 , 好消息是你无需精通JVM 。JVM自己会做好代码编译和优化的工作 , 所以你无需关心如何针对目标平台架构来编写应用程序才能编译、优化 , 从而生成更好的本地机器指令 。
从字节码到可运行的程序
当你编写完Java源代码并将之编译为字节码后 , 下一步就是将字节码指令编译为本地机器指令 。这一步会由解释器或编译器完成 。
解释
解释是最简单的字节码编译形式 。解释器查找每条字节码指令对应的硬件指令 , 再由CPU执行相应的硬件指令 。
你可以将解释器想象为一个字典:每个单词(字节码指令)都有准确的解释(本地机器指令) 。由于解释器每次读取一个字节码指令并立即执行 , 因此它就没有机会对某个指令集合进行优化 。由于每次执行字节码时 , 解释器都需要做相应的解释工作 , 因此程序运行起来就很慢 。解释执行可以准确执行字节码 , 但是未经优化而输出的指令集难以发挥目标平台处理器的最佳性能 。
编译
另一方面 , 编译执行应用程序时 , *编译器*会将加载运行时会用到的全部代码 。因为编译器可以将字节码编译为本地代码 , 因此它可以获取到完整或部分运行时上下文信息 , 并依据收集到的信息决定到底应该如何编译字节码 。编译器是根据诸如指令的不同执行分支和运行时上下文数据等代码信息来指定决策的 。
当字节码序列被编译为机器代码指令集合时 , 就可以对这个指令集合做一些优化操作了 , 优化后的指令集合会被存储到成为code cache的数据结构中 。当下一次执行这部分字节码序列时 , 就会执行这些经过优化后被存储到code cache的指令集合 。在某些情况下 , 性能计数器会失效 , 并覆盖掉先前所做的优化 , 这时 , 编译器会执行一次新的优化过程 。使用code cache的好处是优化后的指令集可以立即执行 —— 无需像解释器一样再经过查找的过程或编译过程!这可以加速程序运行 , 尤其是像Java应用程序这种同一个方法会被多次调用应用程序 。
优化
随着动态编译器一起出现的是性能计数器 。例如 , 编译器会插入性能计数器 , 以统计每个字节码块(对应与某个被调用的方法)的调用次数 。在进行相关优化时 , 编译器会使用收集到的数据来判断某个字节码块有多“热” , 这样可以最大程度的降低对当前应用程序的影响 。运行时数据监控有助于编译器完成多种代码优化工作 , 进一步提升代码执行性能 。随着收集到的运行时数据越来越多 , 编译器就可以完成一些额外的、更加复杂的代码优化工作 , 例如编译出更高质量的目标代码 , 使用运行效率更高的代码替换原代码 , 甚至是剔除冗余操作等 。
- 「干货」告诉你Pr的预览和渲染到底吃什么配置,如何提升性能
- 锐龙R5 3600 vs i5-9400F游戏性能评测:究竟谁是弟弟?
- 荣耀v30跟v30pro处理器一样,但是性能差距很大,这是为什么呢?
- oppofindx2pro这台手机性能如何?
- VIVO?z5x手机的耐用性能怎么样?
- 被误解的iPhone xsMAX防水性能,抗水不等于防水,进水后没有保修
- 怎么看显卡性能
- 「干货」告诉你Pr的预览和渲染到底吃什么配置,如何提升性能
- 红米k30pro对比小米10pro拍照性能如何?
- 最高性能芯片来袭!华为今日推出7纳米鲲鹏920芯片