即时编译器的逃逸分析及优化

一、概念

逃逸分析指的是对象是否会逃逸出当前方法,进入堆内存中或者作为参数传入被未知方法引用。如果在堆中那么该对象会被所有线程看见并引用,未知方法包括虚方法,对象传入虚方法中就算逃逸。逃逸分析可以根据逃逸范围实现以下多个编译优化的好处,缺点是分析本身需要消耗一定的CPU资源;

逃逸:因为当对象被多个线程引用或者被虚方法引用时,编译器无法定位对象的位置,所以被认为是逃逸了;

逃逸范围:(范围由小到大)

  • 不逃逸:只在一个方法中被引用(支持同步消除、标量替换、栈上分配优化)
  • 方法逃逸:在同一个线程内的多个方法中被作为参数传递(不支持标量替换优化)
  • 线程逃逸:在多个线程中被引用(不支持栈上分配优化)

请添加图片描述

二、基于逃逸分析的编译优化

优化一:
同步消除当对象不会逃逸出当前线程时,在对象上加的锁会被虚拟机优化去除,因为该对象不会被其他线程引用,是线程安全的(比如在单线程中的对象上加的锁)

优化二:
标量替换指的是不再将对象存储在堆中,而是用一个个单独的局部变量组合成对象具体的内容,并且将这些局部变量分开存储在栈或者寄存器中。这样就可以减轻GC的压力了,而且还可以节省内存空间。

对象标量替换的条件:不会发生逃逸的对象,也就是不需要放入到堆中供所有线程引用的对象 — 这里指的是方法中new的对象,不发生方法逃逸的对象

优化三:
栈上分配理论上可以将这类不逃逸的对象放入到栈帧中(不在堆中分配内存),也就是栈上分配,但是实现过程复杂,HotSpot没有将其实现,所以用标量替换代替了 — 这里指的是不发生线程逃逸的对象(线程中包含多个方法,每个方法内部可能会new对象)。

优化四:
部分逃逸分析:指的是对象不一定会发生逃逸,在某些情况下当满足判断条件进入另一块程序时对象才会发生逃逸(比如if语句)。

为了减少对象创建,即时编译器会将对象在堆中建立的时间推延至该对象发生逃逸的时间点,如果该对象在极大概率下不会发生逃逸,那么就可以通过上述标量替换的方法达到优化的目的。

参考文章

https://time.geekbang.org/column/article/18048

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值