JVM的栈上分配与逃逸分析

一、栈上分配

栈上分配主要是指在Java程序的执行过程中,在方法体中声明的变量以及创建的对象,将直接从该线程所使用的栈中分配空间。 一般而言,创建对象都是从堆中来分配的,这里是指在栈上来分配空间给新创建的对象。

二、逃逸分析

逃逸是指在某个方法之内创建的对象,除了在方法体之内被引用之外,还在方法体之外被其它变量引用到;这样带来的后果是在该方法执行完毕之后,该方法中创建的对象将无法被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);
    }

    public void getInstance() {
        //对象的作用域只在当前方法中有效,没有发生逃逸
        Object obj1 = new Object();
    }
}

运行java时传递jvm参数 -XX:+DoEscapeAnalysis

三、栈上分配与逃逸分析的关系

进行逃逸分析之后,产生的后果是所有的对象都将由栈上分配,而非从JVM内存模型中的堆来分配。

栈上分配可以提升代码性能,降低在多线程情况下的锁使用,但是会受限于其空间的大小。

分析找到未逃逸的变量,将变量类的实例化内存直接在栈里分配(无需进入堆),分配完成后,继续在调用栈内执行,最后线程结束,栈空间被回收,局部变量对象也被回收。

能在方法内创建对象,就不要再方法外创建对象。

猜你喜欢

转载自blog.csdn.net/xiaoshiyiqie/article/details/80755983