逃逸分析、栈上分配、TLAB

引言

       我们知道,一般在java程序中,new的对象是分配在堆空间中的,但是实际的情况是,大部分的new对象会进入堆空间中,而并非是全部的对象,还有另外两个地方可以存储new的对象,我们称之为栈上分配以及TLAB。

栈上分配

为什么需要栈上分配

       在我们的应用程序中,其实有很多的对象的作用域都不会逃逸出方法外,也就是说该对象的生命周期会随着方法的调用开始而开始,方法的调用结束而结束,对于这种对象,是不是该考虑将对象不在分配在堆空间中呢?

       因为一旦分配在堆空间中,当方法调用结束,没有了引用指向该对象,该对象就需要被gc回收,而如果存在大量的这种情况,对gc来说无疑是一种负担。

        因此,JVM提供了一种叫做栈上分配的概念,针对那些作用域不会逃逸出方法的对象,在分配内存时不在将对象分配在堆内存中,而是将对象属性打散后分配在栈(线程私有的,属于栈内存)上,这样,随着方法的调用结束,栈空间的回收就会随着将栈上分配的打散后的对象回收掉,不再给gc增加额外的无用负担,从而提升应用程序整体的性能。

方法逃逸,如下:就是方法内的对象,可以被方法外所访问,对象实例放在堆上。

public class EscapeTest {

    public static Object obj;
    public void globalVariableEscape() {
 // 给全局变量赋值,发生逃逸
        obj = new Object();
    }
    public Object methodEscape() {
 // 方法返回值,发生逃逸
        return new Object();
    }
    public void instanceEscape() {
 // 实例引用发生逃逸
        test(this); 
    }
}

jvm根据对象是否发生逃逸,会分配到不同(堆或栈)的存储空间:

  • 如果对象发生逃逸,那会分配到堆中。(因为对象发生了逃逸,就代表这个对象可以被外部访问,换句话说,就是可以共享,能共享数据的,无非就是堆或方法区,这里就是堆。)
  • 如果对象没发生逃逸,那会分配到栈中。(因为对象没发生逃逸,那就代表这个对象不能被外部访问,换句话说,就是不可共享,这里就是栈。)
  • 那我们再想深一层,为什么会有逃逸分析,有栈上分配这些东西?
  • 当然是为了主体的考虑,主体就是jvm,或者直接说为了GC考虑也不为过。大家想想,GC主要回收的对象是堆和方法区。GC不会对栈、程序计数器这些进行回收的,因为没东西可以回收。
  • 说回来,如果方法逃逸,那么对象就会分配在堆中,这个时候,GC就要工作了。如果没发生方法逃逸,那么对象就分配在栈中,当方法结束后,资源就自动释放了,GC压根不用操心。所以哈,方法逃逸这东西,主要也是为GC打工的,或者说为GC服务吧!说到这里,可能有人会问,那方法逃逸和性能还是没关系哈?emmm!!!其实有,想深一层,GC不运行的时候,程序的性能肯定会好点,不会占用程序运行的时间。虽然GC清扫垃圾的速度很快,但是当一个程序足够大的时候,对象就自然多了,垃圾也自然多了,这个时候GC就忙了。

栈上分配如何开启

栈上分配需要有一定的前提:

  • -server JVM运行的模式之一, server模式才能进行逃逸分析, JVM运行的模式还有mix/client

  • -XX:+PrintGC:打印GC日志

  • 开启逃逸分析 (-XX:+DoEscapeAnalysis)

逃逸分析的作用就是分析对象的作用域是否会逃逸出方法之外,再server虚拟机模式下才可以开启(jdk1.6默认开启)

  • 开启标量替换 (-XX:+EliminateAllocations):标量替换的作用是允许将对象根据属性打散后分配再栈上,默认该配置为开启
  • -XX:-UseTLAB 关闭本地线程分配缓冲

如何查看逃逸分析的筛选结果

可以通过配置 -XX:+PrintEscapeAnalysis 开启打印逃逸分析筛选结果

TLAB(ThreadLocalAllocBuffer,本地线程分配缓冲)

为什么需要TLAB

       我们知道,对象分配在堆上,而堆是一个全局共享的区域,当多个线程同一时刻操作堆内存分配对象空间时,就需要进行同步,而同步带来的效果就是对象分配效率变差(尽管JVM采用了CAS的形式处理分配失败的情况),但是对于存在竞争激烈的分配场合仍然会导致效率变差。

       那么能不能构造一种线程私有的堆空间(实际上是Eden区中划出的),哪怕这块堆空间特别小,但是只要有,就可以每个线程在分配对象到堆空间时,先分配到自己所属的那一块堆空间中,避免同步带来的效率问题,从而提高分配效率。

逃逸分析、栈上分配、TLAB_第1张图片

你可能感兴趣的:(【JVM】)