JVM逃逸分析,作用及实战案例

一,是什么是逃逸分析?

逃逸分析是分析指针可以存储的所有地方,用于判断指针是否能确保在当前线程。
我理解的就是用来分析,一个对象是否仅在某个线程被访问到。

二,为什么要进行逃逸分析?

在JIT时,进行逃逸分析后,就可以确定对象仅在某一线程中被访问到,这样JIT就可以对其方法进行优化。
包括:
1.堆分配转化为栈分配
2.锁消除
3.分离对象或标量替换
具体方式见下文。

三,判断逃逸的标准有哪些?

1.对象被赋值给堆中的变量或者类的静态变量
2.对象被传进了不确定的代码中运行
下面举几个例子

public class EscapeTest {

    public static Object globalVariableObject;

    public Object instanceObject;

    public void globalVariableEscape(){
        globalVariableObject = new Object(); //静态变量,外部线程可见,发生逃逸
    }

    public void instanceObjectEscape(){
        instanceObject = new Object(); //赋值给堆中实例字段,外部线程可见,发生逃逸
    }
    
    public Object returnObjectEscape(){
        return new Object();  //返回实例,外部线程可见,发生逃逸
    }

    public void noEscape(){
        synchronized (new Object()){
            //仅创建线程可见,对象无逃逸
        }
        Object noEscape = new Object();  //仅创建线程可见,对象无逃逸
    }

}

四,基于逃逸分析的优化

1.堆分配转化为栈分配
如果一个对象的指针不会发生逃逸,那么就可以把该对象分配在栈上,这样在栈帧弹出时回收该对象,不用等到gc时,从而降低gc压力和频率。
2.锁消除
如果一个对象不会发生逃逸,只被一个线程访问,那么在这个对象上的操作就不需要进行同步
3.分离对象或标量替换
如果一个对象不会发生逃逸,可以将该对象分解成一个个基本变量,分配栈上。这样有两点好处,1.不用再生成对象头,从而减少开销。2.空间回收更为高效,同其他栈分配资源。

五,逃逸分析优化案例

1.堆分配转化为栈分配
虚拟机配置参数:-XX:+PrintGC -Xms20M -Xmn20M -XX:+DoEscapeAnalysis

-XX:+DoEscapeAnalysis表示开启逃逸分析,JDK8是默认开启的

-XX:+PrintGC 表示打印GC信息

-Xms20M -Xmn20M 设置JVM内存大小是20M
JVM逃逸分析,作用及实战案例_第1张图片

public static void main(String[] args){
        for(int i = 0; i < 5_000_000; i++){
            createObject();
        }
    }

    public static void createObject(){
        new Object();
    }

运行结果,没有进行频繁的gc
JVM逃逸分析,作用及实战案例_第2张图片

将逃逸分析关闭 -XX:-DoEscapeAnalysis
JVM逃逸分析,作用及实战案例_第3张图片
再次运行
JVM逃逸分析,作用及实战案例_第4张图片
发生频繁的gc

2.锁消除
虚拟机配置参数:-XX:+PrintGC -Xms500M -Xmn500M -XX:+DoEscapeAnalysis。配置500M是保证不触发GC。
JVM逃逸分析,作用及实战案例_第5张图片
开启逃逸分析时,用了4毫秒。
注意这个耗时,跟不加锁的上面测试是一致的。

现在关闭逃逸分析再测
JVM逃逸分析,作用及实战案例_第6张图片
用了111ms。

以上

你可能感兴趣的:(性能优化,源码分析,jvm)