Java中的栈上分配

博客搬家自https://my.oschina.net/itsyizu/blog/

什么是栈上分配

栈上分配是java虚拟机提供的一种优化技术,基本思想是对于那些线程私有的对象(指的是不可能被其他线程访问的对象),可以将它们打散分配在栈上,而不是分配在堆上。分配在栈上的好处是可以在函数调用结束后自行销毁,而不需要垃圾回收器的介入,从而提供系统的性能。

栈上分配的一个技术基础是进行逃逸分析。逃逸分析的目的是判断对象的作用域是否有可能逃逸出函数体。

下面的代码显示了一个逃逸的对象:

public class PartionOnStack {
   static class User{
    private int id;
    private String name;
    public User(){}
       }
    private static  User user;
    public static void foo() {
    user=new User();
    user.id=1;
    user.name="sixtrees";
    }
    public static void main(String[] args) {
    foo();
    }

}

因为上面的代码中的User的作用域是整个Main Class,所以user对象是可以逃逸出函数体的。下面的代码展示的则是一个不能逃逸的代码段。

public class PartionOnStack {
    class User{
    private int id;
    private String name;
    public User(){}
       }
    public  void foo() {
    User user=new User();
    user.id=1;
    user.name="sixtrees";
    }
    public static void main(String[] args) {
    PartionOnStack pos=new PartionOnStack();
    pos.foo();
    }

}

代码来帮忙

通过上面的分析,我们知道java虚拟机会帮助我们在栈上进行分配,我们设置了1亿次alloc的对象创建,每个User对象实例需要占用16字节的空间,如果没有优化,累计的空间申请将有1.5GB这么大,如果我们的堆空间设置的值小于1.5GB的话,就会发生GC。代码如下:

public class PartionOnStack {
    class User{
    public int id;
    public String name;
       }
    public  void foo() {
    User user=new User();
    user.id=1;
    user.name="sixtrees";
    }
    public static void main(String[] args) {
    System.out.println("start-----------");
    long beginTime=System.currentTimeMillis();
    PartionOnStack pos=new PartionOnStack();
    for(int i=0;i<100000000;i++)
    {     
        pos.foo();
    }
    long endTime=System.currentTimeMillis();
    System.out.println("总共运行----"+(endTime-beginTime)+"ms");
    }

}

使用下面的参数运行上面的代码

-server -XMX10m -Xms10m -XX:+DoEscapeAnalysis -XX:+PrintGC -XX:-UseTLAB -XX:+EliminateAllocations

运行的结果如下所示:

image

对于大量的零散小对象,栈上分配提供了一种很好的对象分配策略,栈上分配的速度快,并且可以有效地避免垃圾回收带来的负面的影响,但由于和堆空间相比,栈空间比较小,因此对于大对象无法也不适合在栈上进行分配。

posted @ 2017-02-18 23:50  shugen  阅读(837)  评论(0编辑  收藏  举报