深入理解JVM学习笔记-运行期优化

Java程序最初是通过解释器进行解释执行的,当虚拟机发现某个方法或者代码块运行特别频繁时,就会把这些代码认定为热点代码,为了提高热点代码的执行效率,运行时虚拟机将会把热点代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器。即时编译生成机器相关的中间码,可重复执行缓存效率高。解释执行直接执行字节码,重复执行需要重复解释。
即时编译(JIT)与预编译(AOT):在Dalvik下,应用每次运行都需要通过即时编译器(JIT)将字节码转换为机器码,即每次都要编译加运行,这虽然会使安装过程比较快,但是会拖慢应用的运行效率。而在ART 环境中,应用在第一次安装的时候,字节码就会预编译(AOT)成机器码,这样的话,虽然设备和应用的首次启动(安装慢了)会变慢,但是以后每次每次打开应用,执行的都是本地机器码。移除了运行时的解释执行都可以直接运行,因此运行效率会提高。Android7.0版本ART加入了即时编译器JIT,作为AOT的一个补充,在应用程序安装时并不会将字节码全部编译成机器码,在运行中将热点代码编译成机器码,从而缩短应用程序的安装时间并节省存储空间。
解释执行:将编译好的字节码一行一行地翻译为机器码执行。编译执行:以方法为单位,将字节码一次性翻译为机器码后执行。当程序需要迅速启动和执行时,解释器可以首先发挥作用,省去编译的时间,立即执行;当程序运行后,随着时间的推移,编译器逐渐会失去作用,把越来越多的代码编译成本地代码后,可以获取更高的执行效率。解释执行可以节约内存,而编译执行可以提升效率。目前主流的HotSpot虚拟机中默认是采用解释器与其中一个编译器直接配合的方式工作。

编译对象与触发条件

运行过程中会被即时编译器编译的热点代有两类:
(1)被多次调用的方法。
(2)被多次调用的循环体。
以上两种情况,编译器都是以整个方法作为编译对象,这种编译也是虚拟机中标准的编译方式。一段代码或方法是不是热点代码,是不是需要触发即时编译,需要进行Hot Spot Detection(热点探测)。
目前主要的热点 判定方式有以下两种:
(1)基于采样的热点探测:虚拟机会周期性地检查各个线程的栈顶,如果发现某些方法经常出现在栈顶,那这段方法代码就是“热点代码”。好处是:实现简单高效,还可以很容易地获取方法调用关系;缺点是:很难精确地确认一个方法的热度,容易因为受到线程阻塞或别的外界因素的影响而扰乱热点探测。
(2)基于计数器的热点探测:虚拟机会为每个方法,甚至是代码块建立计数器,统计方法的执行次数,如果执行次数超过一定的阀值,就认为它是“热点方法”。这种统计方法实现复杂一些,需要为每个方法建立并维护计数器,而且不能直接获取到方法的调用关系,但是它的统计结果相对更加精确严谨。
在HotSpot虚拟机中使用的是第二种——基于计数器的热点探测方法的两个计数器:
(1)方法调用计数器:用来统计方法调用的次数,在默认设置下,方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,即一段时间内方法被调用的次数。
(2)回边计数器:用于统计一个方法中循环体代码执行的次数.
(准确地说,应该是回边的次数,因为并非所有的循环都是回边),在字节码中遇到控制流向后跳转的指令就称为“回边”。
在确定虚拟机运行参数的前提下,这两个计数器都有一个确定的阀值,当计数器的值超过了阀值,就会触发JIT编译。
即时编译和解释执行的执行顺序:发了JIT编译后,在默认设置下,执行引擎并不会同步等待编译请求完成,而是继续进入解释器按照解释方式执行字节码,直到提交的请求被编译器编译完成为止(编译工作在后台线程中进行)。当编译工作完成后,下一次调用该方法或代码时,就会使用已编译的版本。方法调用计数器触发即时编译的流程:方法计数器触发即时编译的过程与回边计数器触发即时编译的过程类似。方法调用计数器触发即时编译流程如下图所示:

方法调用技术器触发即时编译.png

编译优化技术

以编译方式执行本地代码比解释方式更快,除去虚拟机执行字节码时额外消耗时间的原因外,还有一个重要原因,虚拟机设计团队几乎把对代码的所有优化措施都集中在了即时编译器之中,代码优化变换是建立在代码的某种中间标志或者机器码之上,绝不是建立在java源码之上的。华为方舟编译器直接将代码优化从手机环节搬到了开发者环境,可以在很多地方对代码进行优化,同时即时编译器本地代码比javac产生的的字节码更优秀。
即时编译器针对不同的类型有不同的优化技术,具体可以参考《深入理解JVM》,几种比较有代表性的优化技术有:
(1)语言无关的经典优化技术之一:公共子表达式消除

int d = (C*B)*12 +a + (A+B*C)
int d = (E)*12 + a +A + E;
int d = 13E +2A;

以上就是公共子表达式消除;
(2)语言相关的经典优化技术之一:数组范围检测消除:数组边界检查肯定是必须做的,但是数组边界检查不是必须在运行期间一次不漏的检查,如果通过数据流分析可以判断循环变量的取值永远在数组边界之内,就可以在循环中将数组上下界检测消除。
(3)最重要的优化技术之一:方法内联:方法内联就是消除一些无用的代码,如方法一已经进行了null判断,如果调用方法二又进行了null判断,实际两次null判断仅需要一次。
(4)最前沿的优化技术之一:逃逸分析:如果一个对象不会逃逸到方法或者线程之外,也就是别的方法或线程无法通过任何途径访问到这个对象,则可能为这个变量进行一些高校的优化,例如本来是堆上分配的变量发现没有其他线程使用,可以将其分配到栈上,栈上分配的对象就会随着方法的结束而自动销毁。
(5)同步消除(synchronized):类似于锁优化,变量不会逃逸到出方法,就可以将该方法上的同步锁去掉,相关内容请参考《深入理解JVM》线程安全与锁优化章节。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容