zoukankan      html  css  js  c++  java
  • JVM即时编译器优化

       阅读《深入理解Java虚拟机》的过程中,会碰到一些不明就里的名词。虽然大概知道意思,但是如果一眼飘过去,估计过不了多久就会遗忘。这里单独提出来,去查阅资料,先形成自己的理解,再继续往下对比着看。

      原文:Java世界里“几乎”所有的对象实例都在这里分配内存。在《Java虚拟机规范》中对Java堆的描述是:“所有的对象实例以及数组都应当在堆上分配”现在已经能看到些许迹象表明日后可能出现值类型的支持。但即使只考虑现在,由于即时编译技术的进步......

      这里的意思是说,JVM堆中并不是包含所有的分配的对象实例,由于JVM堆优化的技术,有些对象实例并不是分配在JVM堆内存中。这里的即时编译器是什么意思呢?我们首先看一幅图:

      

      首先,我们的源代码通过编译器(如javac)被编译成了字节码文件(.class)。其它的语言如Groovy, Scala也可以通过自身的编译器被编译为字节码文件。这个过程我们称之为编译期。

      而后的解释执行阶段,我们称之为运行期。JVM会将字节码文件加载进虚拟机之后,由Java解释器将字节码一句一句地转换为机器码执行。从这个角度上来说,Java是依靠解释执行。但在JVM地不断发展中,人们想在解释执行这个过程中,做一些优化,以提升JVM的性能,其实这也是商用JVM的必由之路。

      JVM在执行期间,如果发现某块代码或者方法执行地特别频繁,就会将这一部分代码标记为热点代码。一旦被标记为热点代码,那么JIT编译器(Just in time Compiler)就会对此部分代码进行深度优化(虚拟机设计团队几乎把所有的优化措施都使用上了),而后输出一份编译后的机器码(质量很高,执行效率很高),当这个热点代码再次执行时,就会直接采用已经编译好的机器码,而不是由解释器一句一句地翻译,从而提升了执行速度。

      但这个过程中,有几点需要明确:

      1.如果只是执行一次,那么解释器的速度会比即时编译器高;但多次反复执行的代码,解释器的速度是不如编译一次,多次执行的即时编译器的,这是时间上的损耗;

      2.即时编译器编译之后的代码(缓存在方法区)体积会膨胀,这是一个比较消耗内存的过程,这是空间上的损耗。

      所以一般的JVM都是将解释器和编译器结合使用,以追求时间和空间的平衡。程序首次启动或者执行时,可以让解释器快速地先执行。而多次调用的方法或者循环体时,JIT即时编译器可以发挥作用,提升速度。我们可以在cmd中查看三种模式,混合模式,纯解释器模式以及编译器(在编译器无法进行时还是需要解释器)模式:

      

      Hotspot两种即时编译器为C1(客户端编译器)与C2(服务端编译器),前者编译速度快更轻量,而后者编译质量更高更重量级。具体使用哪一种编译器由JVM根据环境自动选择,但用户也可以强制指定某种模式。上图中的混合模式,即C1C2其中的一种编译器和解释器混合执行。

      那么虚拟机是怎么判断方法是热点代码呢?

      1.JVM周期性地检查各个栈的栈顶,如果某个方法经常出现在栈顶,那么标记为热点代码。

      2.为每个方法建立计数器,执行次数超过阈值就认为是“热点方法”。

      对比起来,第一种简单高效,但是比较粗糙不精确,容易受到外因干扰,第二种很精确但是实现起来很麻烦。

      【参考】

      https://blog.csdn.net/lanzhupi/article/details/112727660

  • 相关阅读:
    第一个ExtJS练习(添加用户面板)
    利用高德地图通过给定坐标点画带箭头方向的路径
    安装myeclipse2015 stable 3.0破解之后发生出现SECURITY ALERT:iNTEGRITY CHECK ERROR然后闪退解决方案
    当你的SSM项目中的springmvc.xml发生第一行错误解决方案
    新建maven项目遇到Select an Archetype时没有maven-archetype-webapp处理方法
    XML、HTML、JSON对比
    Mac配置apache2.4.25服务器
    使用HTTP协议访问网络
    android数据持久化存储
    常用git命令
  • 原文地址:https://www.cnblogs.com/bruceChan0018/p/15041749.html
Copyright © 2011-2022 走看看