Java中的逃逸分析

1:JIT(Just In Time Compiler即时编译器):虚拟机为了提高执行热点代码(对于某个方法活代码块执行频率非常频繁时,认定这些代码时热点代码)的效率,在运行时会将这些代码编译为与本地平台相关的机器码,并进行各种层次优化,完成这个任务的编译器称为即时编译器。

2:对象逃逸: 它并不是一种直接优化代码的手段,而是为其它优化手段提供依据的分析技术(通过此技术可以判定哪些代码可以被优化,如何被优化)。逃逸分析的基本行为就是分析对象动态作用域。一般分为两种方式:方法逃逸和线程逃逸

  1. 方法逃逸:当一个对象在方法中被定义后,它可能被外部方法所引用则称为方法逃逸。例如用该对象作为调用参数传递到其它方法中。

  2. 线程逃逸:当一个对象在方法中被定义后如果能外部线程访问则为线程逃逸。比如将该对象赋值给类变量或可以在其它线程中访问该对象

如果能证明一个对象不会逃逸到方法或线程之外,也就是说别的方法或者线程无法通过任何途径访问这个对象,则可能对这个变量进行一些高效的优化

2.1栈上分配:

一般对象的内存空间是在堆上被分配,堆中数据对于所有线程都是可见的,只要拥有该对象引用,就可以访问堆中存储的数据。一般情况下虚拟机的垃圾回收机制大部分时间都在回收堆中对象,不论是确定对象是否需要被回收,还是回收对象整个过程都是需要cpu资源以及时间的(具体可参考垃圾回收机制)。但如果确定一个对象不会逃逸方法之外,那么我们可以在栈内分配该内存,而对象内存的销毁可以伴随着栈帧出栈(方法执行结束)而进行。如果我们的应用中不会逃逸的局部对象占比很大,如果使用栈上分配,大量的对象随着方法的结束而自动销毁,可以极大减少垃圾回收器的压力。所以在编写代码时可以尽量使用不可逃逸的局部变量(不仅减少垃圾回收器的压力而且也避免多线程环境下的线程安全问题)。

demo代码:

 /**
     * 栈上分配
     */
    public void stackAllocation(){

        StringBuilder sb = new StringBuilder();
        sb.append("t1");
        sb.append("t2'");
    }

    /**
     * 没有栈上分配
     */
    public void noStackAllocation(){
        StringBuilder sb = new StringBuilder();
        sb.append("t1");
        sb.append("t2'");
        test(sb);
    }

    public  void test(StringBuilder sb){}

2.2同步消除:

在多线程环境下,如果逃逸分析能够确定某变量是不会逃逸出线程,无法被其它线程访问。那么这个变量的读写肯定是不会存在线程安全问题,那么对于这个变量所加的一系列的同步措施也就被消除了。

demo代码:

    /**
     * 
     * 同步消除
     */
    public  void synchronousElimination(){

        StringBuilder sb = new StringBuilder();

        synchronized (sb){
            sb.append("test");
        }
    }

    //上述代码在JIT编译阶段就会被优化成(去除同步机制):
    public  void synchronousElimination(){

        StringBuilder sb = new StringBuilder();

        sb.append("test");
    }

2.3标量替换:

标量(Scalar)是指一个数据无法再分解成更小的数据来表示,java中基础数据类型(int,long等数值类型以及reference类型)都不能再进一步分解。对应如果一个数据可以继续分解,那么就称为聚合量(Aggregate).逃逸分析如果能够确定一个对象不会被外部访问,并且这个对象是可以被分解的,那么程序运行时不一定会创建这个对象,而改为创建它的若干个被这个方法使用到的成员变量来代替。将对象拆分之后,成员变量可以直接在栈上(栈上存储的数据,有很大的概率会被虚拟机分配到物理机器的高速寄存器中存储)分配和读写(减少垃圾回收器回收压力)

如何开启逃逸分析:

  1. -XX:+DoEscapeAnalysis开启逃逸分析(jdk1.8默认开启)开启之后可以使用参数-XX:+PrintEscapeAnalysis查看分析结果
  2. -XX:-DoEscapeAnalysis 关闭逃逸分析
  3. -XX:+EliminateLocks开启同步消除-基本就是锁消除(jdk1.8默认开启)
  4. -XX:-EliminateLocks 关闭同步消除
  5. -XX:+EliminateAllocations开启标量替换(jdk1.8默认开启)开启之后使用参数-XX:+PrintEliminateAllocations查看标量替换情况
  6. -XX:-EliminateAllocations 关闭标量替换

 

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值