Java中的栈上分配

1.什么是栈上分配

栈上分配是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();
    }
   
}

2.代码来帮忙

通过上面的分析,我们知道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

运行的结果如下所示:

Java中的栈上分配_第1张图片

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

你可能感兴趣的:(Java中的栈上分配)