【JVM大厂进阶知识点】——>逃逸分析之你能知多少?

在这里插入图片描述




逃逸分析技术




逃逸分析的基本原理:分析对象的动态作用域

  • 当一个对象在方法里被定义之后,它可能被外部的方法引用,例如:作为调用参数传递到其他方法中,这种现象被称为 方法逃逸
  • 甚至还有可能被外部线程访问到,例如:赋值给可以在其他线程访问到的实例变量,这称为 线程逃逸。

对象从低到高逃逸程度:从不逃逸——> 方法逃逸 ——> 线程逃逸。

如果能证明一个对象不会逃逸到方法或线程之外,或者逃逸程度较低(只逃逸方法之外,没逃逸出线程之外)那么就可以对对象进行不同程度的优化。



栈上分配:

我们都知道Java中的对象是在堆中创建,但是 如果确定了一个对象不会逃逸出线程之外,那么可以将该对象在栈上分配随着方法的结束而自动销毁。栈上分配可支持方法逃逸,不支持线程逃逸。



标量替换:

若一个数据已经无法再分解为更小的数据来表示,那么这些数据就成为标量。

原始数据类型(int、long的等数值类型和 引用类型)都不能进一步分解

如果一个数据可以继续分解,那么该数据称为 聚合量。

Java中的对象就是典型聚合量

如果把一个Java对象拆散,根据程序的访问,将使用到的成员变量恢复到原始类型来访问,这个过程就称为 标量替换

如果根据逃逸分析证明一个对象不会逃逸到方法之外,并且这个对象可以被拆散,那么程序真正执行的时候就不会去创建这个对象,而是直接创建它若干个被这个方法使用到的成员变量来代替。&

这样就使得对象成员变量在栈上分配个读写。

标量替换不允许对象逃逸出方法之外。



同步消除

如果逃逸分析能够确定一个变量不会逃逸出线程,无法被其他线程访问到,那么这个变量的读写就不会产生竞争,那么对于该变量的同步措施就可以消除。




伪代码案例

初始代码

public class Main {


    public int test(int x) {
        int tmp = x + 2;
        Point point = new Point(tmp, 3);
        return point.getX();
    }

}

class Point {

    int x;
    int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

第一步:将Point构造函数和getX()方法进行内联优化

public class Main {


    public int test(int x) {
        int tmp = x + 2;
        Point point = point_memory_alloc(); //在堆中分配Point对象的示意方法
        point.x = tmp;
        point.y = 3;
        return point.x;
    }

}

class Point {

    int x;
    int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

第二步:逃逸分析

根据逃逸分析技术可发现,point对象只在test()方法之中使用,故没有发生逃逸,那么就可对point对象进行 标量替换。

public class Main {


    public int test(int x) {
        int tmp = x + 2;
        int px = tmp; //标量替换
        int py = 3;
        return px;
    }

}

class Point {

    int x;
    int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

第三步:通过数据流分析,发现py的值不会对结果造成任何影响,故还可以使用无效代码消除技术进行优化。最后优化如下:

public class Main {


    public int test(int x) {
        return x + 2; //无效代码消除后
    }

}

class Point {

    int x;
    int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

不得不说 编译器优化技术是真的牛皮👍👍👍!


最后说一句 Synchronized的锁优化技术中的 锁消除就是使用到了逃逸分析技术,面试的时候可打出来加分哦,(●ˇ∀ˇ●)。

面试官:Synchronized锁优化、锁升级你知道多少?




最后

我是 Code皮皮虾,一个热爱分享知识的 皮皮虾爱好者,未来的日子里会不断更新出对大家有益的博文,期待大家的关注!!!

创作不易,如果这篇博文对各位有帮助,希望各位小伙伴可以一键三连哦!,感谢支持,我们下次再见~~~

分享大纲

大厂面试题专栏


Java从入门到入坟学习路线目录索引


开源爬虫实例教程目录索引

更多精彩内容分享,请点击 Hello World (●’◡’●)


在这里插入图片描述

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值